mirror of
https://github.com/asterisk/asterisk.git
synced 2026-03-23 22:33:34 +00:00
Compare commits
106 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
30be887c79 | ||
|
|
3dace6b301 | ||
|
|
f6234c6912 | ||
|
|
dcb600ff3b | ||
|
|
80555f6587 | ||
|
|
bab0cfd263 | ||
|
|
8c63834523 | ||
|
|
13f34c3518 | ||
|
|
3eb85f722f | ||
|
|
ee40af15ad | ||
|
|
ceab2dfcf9 | ||
|
|
7336b021e8 | ||
|
|
afd122b895 | ||
|
|
747f8e9238 | ||
|
|
123613853b | ||
|
|
9086941a86 | ||
|
|
4a8dc28b52 | ||
|
|
ed6b4c821e | ||
|
|
ede7bca2a7 | ||
|
|
738689ea86 | ||
|
|
faa9890ff2 | ||
|
|
e055bb6e86 | ||
|
|
b824677a2a | ||
|
|
11fefdc37c | ||
|
|
f18ffcb4b7 | ||
|
|
919b935980 | ||
|
|
5b44727583 | ||
|
|
44ec0d02a2 | ||
|
|
a734901dee | ||
|
|
c75c3e8bc2 | ||
|
|
2a2f2c2c04 | ||
|
|
b3abeb59d3 | ||
|
|
75a75233da | ||
|
|
d5930d1fe8 | ||
|
|
04cde57a77 | ||
|
|
218fdfa3e5 | ||
|
|
0f77c05d85 | ||
|
|
ce47c7f2c7 | ||
|
|
fc8c05165a | ||
|
|
62099ea6b9 | ||
|
|
c918ef0f40 | ||
|
|
b1f7ca718e | ||
|
|
c0a63a9c86 | ||
|
|
61cf4e2668 | ||
|
|
b78dc9e0f6 | ||
|
|
afdafc85ce | ||
|
|
34c34980c6 | ||
|
|
a4cb6c34d3 | ||
|
|
7e81dc97e5 | ||
|
|
7417052303 | ||
|
|
7d19251487 | ||
|
|
f683340aa5 | ||
|
|
bc1141dfff | ||
|
|
f62f33ce93 | ||
|
|
4b75f411fc | ||
|
|
aec202cbdb | ||
|
|
edcd34976e | ||
|
|
3214cf6ba9 | ||
|
|
3f06397045 | ||
|
|
51a5499532 | ||
|
|
5f53621223 | ||
|
|
4a792f6c7c | ||
|
|
60811d944f | ||
|
|
493945c224 | ||
|
|
bc740c86fd | ||
|
|
21b5e17de5 | ||
|
|
6c1cfa8b83 | ||
|
|
3957344c83 | ||
|
|
2ac5d0b1aa | ||
|
|
42b068e43e | ||
|
|
239b43d953 | ||
|
|
31fcc5dbed | ||
|
|
c36135eebf | ||
|
|
0cbb5dd731 | ||
|
|
cf4fe25d62 | ||
|
|
f3140658b4 | ||
|
|
4494a6d2f4 | ||
|
|
09634dde46 | ||
|
|
31c31a718c | ||
|
|
f2784d97fd | ||
|
|
c27ef7f85c | ||
|
|
eb97d576eb | ||
|
|
54e1f06913 | ||
|
|
0051d20a04 | ||
|
|
473cbda85c | ||
|
|
a0e2c58919 | ||
|
|
eac24165f7 | ||
|
|
3a8facf06d | ||
|
|
42a1f82af3 | ||
|
|
5da86a5290 | ||
|
|
364f873573 | ||
|
|
54df359acc | ||
|
|
1983a179c9 | ||
|
|
aefb1f6b06 | ||
|
|
277e550a07 | ||
|
|
e2a5bf3445 | ||
|
|
2ff8edf07b | ||
|
|
55b33a9ef9 | ||
|
|
0327bf310f | ||
|
|
036770fe92 | ||
|
|
0235e1fe05 | ||
|
|
a07f2c930b | ||
|
|
39b383b353 | ||
|
|
e13bb52a79 | ||
|
|
12135c8167 | ||
|
|
dbd257811b |
4
BUGS
4
BUGS
@@ -10,6 +10,10 @@
|
||||
three way call up, the parties in the three way cannot hear one another
|
||||
in the general case.
|
||||
|
||||
* No auto-reload in chan_zap yet
|
||||
|
||||
* Must be able to call park with flash-hook transfer
|
||||
|
||||
======================================================================
|
||||
Short report on the voicemail system
|
||||
======================================================================
|
||||
|
||||
53
CHANGES
53
CHANGES
@@ -1,3 +1,56 @@
|
||||
Asterisk 0.1.12
|
||||
-- Fix for Big Endian machines
|
||||
-- MySQL CDR Engine
|
||||
-- Various SIP fixes and enhancements
|
||||
-- Add "zapateller application and arbitrary tone pairs
|
||||
-- Don't always start at "s"
|
||||
-- Separate linear mode for pseudo and real
|
||||
-- Add initial RTP and SIP support (no jitter buffer yet, unknown stability)
|
||||
-- Add 'h' extension, executed on hangup
|
||||
-- Add duration timer to message info
|
||||
-- Add web based voicemail checking ("make webvmail")
|
||||
-- Add ast_queue_frame function and eliminate frame pipes in most drivers
|
||||
-- Centralize host access (and possibly future ACL's)
|
||||
-- Add Caller*ID on PhoneJack (Thanks Nathan)
|
||||
-- Add "safe_asterisk" wrapper script to auto-restart Asterisk
|
||||
-- Indicate ringback on chan_phone
|
||||
-- Add answer confirmation (press '#' to confirm answer)
|
||||
-- Add distinctive ring support (e.g. Dial,Zap/4r2)
|
||||
-- Add ANSI/vt100 color support
|
||||
-- Make parking configurable through parking.conf
|
||||
-- Fix the empty voicemail problem
|
||||
-- Add Music On Hold
|
||||
-- Add ADSI Compiler (app_adsiprog)
|
||||
-- Extensive DISA re-work to improve tone generation
|
||||
-- Reset all idle channels every 10 minutes on a PRI
|
||||
-- Reset channels which are hungup with "channel in use"
|
||||
-- Implement VNAK support in chan_iax
|
||||
-- Fix chan_oss to support proper hangups and autoanswer
|
||||
-- Make shutdown properly hangup channels
|
||||
-- Add idling capability to chan_zap for idle-net
|
||||
-- Add "MeetMe" conferencing app (app_meetme)
|
||||
-- Add timing information to include
|
||||
Asterisk 0.1.11
|
||||
-- Add ISDN RAS capability
|
||||
-- Add stutter dialtone to Chan Zap
|
||||
-- Add "#include" capability to config files.
|
||||
-- Add call-forward variable to Chan Zap (*72, *73)
|
||||
-- Optimize IAX flow when transfer isn't possible
|
||||
-- Allow transmission of ANI over IAX
|
||||
Asterisk 0.1.10
|
||||
-- Make ast_readstring parameter be the max # of digits, not the max size with \0
|
||||
-- Make up any missing messages on the fly
|
||||
-- Add support for specific DTMF interruption to saying numbers
|
||||
-- Add new "u" and "b" options to condense busy/unavail handling
|
||||
-- Add support for RSA authentication on IAX calls
|
||||
-- Add support for ADSI compatible CPE
|
||||
-- Outgoing call queue
|
||||
-- Remote dialplan fixes for Quicknet
|
||||
-- Added AGI commands supporting TDD functions (RECEIVE CHAR & TDD MODE)
|
||||
-- Added TDD support (send/receive text in chan_zap)
|
||||
-- Fix all strncpy references
|
||||
-- Implement CSV CDR backend
|
||||
-- Implement Call Detail Records
|
||||
Asterisk 0.1.9
|
||||
-- Implement IAX quelching
|
||||
-- Allow Caller*ID to be overridden and suggested
|
||||
|
||||
21
CREDITS
21
CREDITS
@@ -1,17 +1,20 @@
|
||||
=== HARDWARE DONORS ===
|
||||
|
||||
* Special thanks to Adtran, Inc, for their donation of an Adtran Atlas,
|
||||
and TSU 120e to the project. (http://www.adtran.com)
|
||||
|
||||
* Thanks to QuickNet Technologies for their donation of an Internet
|
||||
PhoneJack card to the project. (http://www.quicknet.net)
|
||||
|
||||
=== DEVELOPMENT SUPPORT ===
|
||||
I'd like to thank the following companies for helping fund development of
|
||||
Asterisk:
|
||||
|
||||
* Celera Networks - US Digital
|
||||
* Adtran, Inc.
|
||||
Pilosoft, Inc. - for supporting ADSI development in Asterisk
|
||||
|
||||
GFS - for supporting ALSA development
|
||||
|
||||
Telesthetic - for supporting SIP development
|
||||
|
||||
=== HARDWARE DONORS ===
|
||||
* Thanks to QuickNet Technologies for their donation of an Internet
|
||||
PhoneJack and Linejack card to the project. (http://www.quicknet.net)
|
||||
|
||||
=== MISCELLANEOUS PATCHES ===
|
||||
Oliver Daudey - ISDN4Linux fixes
|
||||
|
||||
=== OTHER SOURCE CODE IN ASTERISK ===
|
||||
|
||||
|
||||
55
HARDWARE
Normal file
55
HARDWARE
Normal file
@@ -0,0 +1,55 @@
|
||||
A PBX is only really useful if you can get calls into it. Of course, you
|
||||
can use Asterisk with VoIP calls (SIP, H.323, IAX), but you can also talk
|
||||
to the real PSTN through various cards.
|
||||
|
||||
Supported Hardware is divided into two general groups: Zaptel devices and
|
||||
non-zaptel devices. The Zaptel compatible hardware supports pseudo-TDM
|
||||
conferencing and all call features through chan_zap, whereas non-zaptel
|
||||
compatible hardware may have different features.
|
||||
|
||||
Zaptel compatible hardware
|
||||
==========================
|
||||
|
||||
-- Linux Support Services, Inc. (Primary author of Asterisk)
|
||||
http://www.linux-support.net, http://store.yahoo.com/asteriskpbx
|
||||
|
||||
* Wildcard X100P - Single FXO interface connects to Loopstart phone
|
||||
line
|
||||
|
||||
* Wildcard T400P - Quad T1 interface connects to four T1/PRI
|
||||
interfaces. Supports RBS and PRI voice and PPP, FR, and HDLC data.
|
||||
|
||||
* Wildcard E400P - Quad E1 interface connects to four E1/PRI (or PRA)
|
||||
interfaces. Supports PRA/PRI, EuroISDN voice and PPP, FR, HDLC data.
|
||||
|
||||
Non-zaptel compatible hardware
|
||||
==============================
|
||||
|
||||
-- QuickNet, Inc.
|
||||
http://www.quicknet.net
|
||||
|
||||
* Internet PhoneJack - Single FXS interface. Supports Linux telephony
|
||||
interface. DSP compression built-in.
|
||||
|
||||
* Internet LineJack - Single FXS or FXO interface. Supports Linux
|
||||
telephony interface.
|
||||
|
||||
|
||||
Miscellaneous other interfaces
|
||||
==============================
|
||||
|
||||
-- ISDN4Linux
|
||||
http://www.isdn4linux.de/
|
||||
|
||||
* Any ISDN terminal adapter supported by isdn4linux should provide
|
||||
connectivity.
|
||||
|
||||
-- ALSA
|
||||
http://www.alsa-project.org
|
||||
|
||||
* Any ALSA compatible full-duplex sound card
|
||||
|
||||
-- OSS
|
||||
http://www.opensound.com
|
||||
|
||||
* Any OSS compatible full-duplex sound card
|
||||
76
Makefile
76
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 -Werror
|
||||
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
|
||||
@@ -37,11 +42,12 @@ CFLAGS+= -DDO_CRASH -DDEBUG_THREADS
|
||||
# Uncomment next one to enable ast_frame tracing (for debugging)
|
||||
#CLFAGS+= -DTRACE_FRAMES
|
||||
CFLAGS+=# -fomit-frame-pointer
|
||||
SUBDIRS=channels pbx apps codecs formats agi
|
||||
LIBS=-ldl -lpthread -lreadline -lncurses -lm
|
||||
SUBDIRS=res channels pbx apps codecs formats agi cdr
|
||||
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 \
|
||||
ulaw.o callerid.o fskmodem.o image.o app.o asterisk.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 acl.o rtp.o asterisk.o
|
||||
CC=gcc
|
||||
INSTALL=install
|
||||
|
||||
@@ -59,10 +65,12 @@ all: asterisk subdirs
|
||||
_version:
|
||||
if [ -d CVS ] && ! [ -f .version ]; then echo "CVS-`date +"%D-%T"`" > .version; fi
|
||||
|
||||
.version: _version
|
||||
|
||||
build.h:
|
||||
./make_build_h
|
||||
|
||||
asterisk: _version build.h $(OBJS)
|
||||
asterisk: .version build.h $(OBJS)
|
||||
gcc -o asterisk -rdynamic $(OBJS) $(LIBS)
|
||||
|
||||
subdirs:
|
||||
@@ -78,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 ; \
|
||||
@@ -90,7 +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
|
||||
@@ -99,6 +111,9 @@ install: all datafiles
|
||||
rm -f $(INSTALL_PREFIX)/usr/lib/asterisk/modules/chan_ixj.so
|
||||
rm -f $(INSTALL_PREFIX)/usr/lib/asterisk/modules/chan_tor.so
|
||||
mkdir -p $(INSTALL_PREFIX)/var/lib/asterisk/sounds
|
||||
mkdir -p $(INSTALL_PREFIX)/var/log/asterisk/cdr-csv
|
||||
mkdir -p $(INSTALL_PREFIX)/var/lib/asterisk/keys
|
||||
install -m 644 keys/iaxtel.pub $(INSTALL_PREFIX)/var/lib/asterisk/keys
|
||||
( cd $(INSTALL_PREFIX)/var/lib/asterisk/sounds ; ln -s ../../../spool/asterisk/vm . )
|
||||
@echo " +---- Asterisk Installation Complete -------+"
|
||||
@echo " + +"
|
||||
@@ -121,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 \
|
||||
@@ -132,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 \
|
||||
@@ -142,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
|
||||
|
||||
@@ -164,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
|
||||
|
||||
|
||||
|
||||
8
README
8
README
@@ -32,6 +32,9 @@ is no requirement that you provide the same exemption in your GPL'd
|
||||
products (although if you've written a module for Asterisk we would
|
||||
strongly encourage you to make the same excemption that we do).
|
||||
|
||||
Specific permission is also granted to OpenSSL and OpenH323 to link to
|
||||
Asterisk.
|
||||
|
||||
If you have any questions, whatsoever, regarding our licensing policy,
|
||||
please contact us.
|
||||
|
||||
@@ -48,9 +51,10 @@ as well.
|
||||
First, be sure you've got supported hardware. To use Asterisk right now,
|
||||
you will need one of the following:
|
||||
|
||||
* Adtran Atlas 800 Plus
|
||||
* QuickNet Internet PhoneJack
|
||||
* All Wildcard (tm) products from LSS (www.linux-support.net)
|
||||
* QuickNet Internet PhoneJack and LineJack (http://www.quicknet.net)
|
||||
* Full Duplex Sound Card supported by Linux
|
||||
* Adtran Atlas 800 Plus
|
||||
* ISDN4Linux compatible ISDN card
|
||||
* Tormenta Dual T1 card (www.bsdtelephony.com.mx)
|
||||
|
||||
|
||||
14
README.cdr
Normal file
14
README.cdr
Normal file
@@ -0,0 +1,14 @@
|
||||
Asterisk now generates Call Detail Records. See include/asterisk/cdr.h for
|
||||
all the fields which are recorded. By default, records in comma-separated
|
||||
values will be created in /var/log/asterisk/cdr-csv. You can specify
|
||||
account codes and AMA (Automated Machine Accounting) flags on a per-channel
|
||||
(Zaptel et al) or per-user (IAX) basis to help with accounting. Look
|
||||
at the top of cdr/cdr_csv.c to see the format for the records.
|
||||
|
||||
ONE IMPORTANT NOTE: If you are trying to collect records on IAX to IAX calls
|
||||
you need to be aware that by default, IAX will attempt to transfer calls
|
||||
in this situation (if DTMF is not required). When the transfer is completed
|
||||
the call is dumped from the middle machine and thus the call detail records
|
||||
will report a short call time. If you want detailed records you must
|
||||
turn off IAX transfer, but unless your servers are very close together, you
|
||||
will definitely get a latency hit from doing so.
|
||||
326
README.iax
Normal file
326
README.iax
Normal file
@@ -0,0 +1,326 @@
|
||||
Inter-Asterisk eXchange Protocol
|
||||
================================
|
||||
|
||||
INTRODUCTION
|
||||
------------
|
||||
|
||||
This document is intended as an introduction to the Inter-Asterisk
|
||||
eXchange (or simply IAX) protocol. It provides both a theoretical
|
||||
background and practical information on its use.
|
||||
|
||||
WHY IAX
|
||||
-------
|
||||
The first question most people are thinking at this point is "Why do you
|
||||
need another VoIP protocol? Why didn't you just use SIP or H.323?"
|
||||
|
||||
Well, the answer is a fairly complicated one, but in a nutshell it's like
|
||||
this... Asterisk is intended as a very flexible and powerful
|
||||
communications tool. As such, the primary feature we need from a VoIP
|
||||
protocol is the ability to meet our own goals with Asterisk, and one with
|
||||
enough flexibility that we could use it as a kind of laboratory for
|
||||
inventing and implementing new concepts in the field. Neither H.323 or
|
||||
SIP fit the roles we needed, so we developed our own protocol, which,
|
||||
while not standards based, provides a number of advantages over both SIP
|
||||
and H.323, some of which are:
|
||||
|
||||
* Interoperability with NAT/PAT/Masquerade firewalls
|
||||
IAX seamlessly interoperates through all sorts of NAT and PAT
|
||||
and other firewalls, including the ability to place and
|
||||
receive calls, and transfer calls to other stations.
|
||||
|
||||
* High performance, low overhead protocol
|
||||
When running on low-bandwidth connections, or when running
|
||||
large numbers of calls, optimized bandwidth utilization is
|
||||
imperitive. IAX uses only 4 bytes of overhead
|
||||
|
||||
* Internationalization support
|
||||
IAX transmits language information, so that remote PBX
|
||||
content can be delivered in the native language of the
|
||||
calling party.
|
||||
|
||||
* Remote dialplan polling
|
||||
IAX allows a PBX or IP phone to poll the availability of a
|
||||
number from a remote server. This allows PBX dialplans to
|
||||
be centralized.
|
||||
|
||||
* Flexible authentication
|
||||
IAX supports cleartext, md5, and RSA authentication,
|
||||
providing flexible security models for outgoing calls and
|
||||
registration services.
|
||||
|
||||
* Multimedia protocol
|
||||
IAX supports the transmission of voice, video, images, text,
|
||||
HTML, DTMF, and URL's. Voice menus can be presented in both
|
||||
audibly and visually.
|
||||
|
||||
* Call statistic gathering
|
||||
IAX gathers statistics about network performance (including
|
||||
latency and jitter, as well as providing end-to-end latency
|
||||
measurement.
|
||||
|
||||
* Call parameter communication
|
||||
Caller*ID, requested extension, requested context, etc are
|
||||
all communicated through the call.
|
||||
|
||||
* Single socket design
|
||||
IAX's single socket design allows up to 32768 calls to be
|
||||
multiplexed.
|
||||
|
||||
While we value the importance of standards based (i.e. SIP) call handling,
|
||||
hopefully this will provide a reasonable explanation of why we developed
|
||||
IAX rather than starting with SIP.
|
||||
|
||||
CONFIG FILE CONVENTIONS
|
||||
-----------------------
|
||||
Lines beginning with '>' represent lines which might appear in an actual
|
||||
configuration file. The '>' is used to help separate them from the
|
||||
descriptive text and should not actually be included in the file itself.
|
||||
|
||||
Lines within []'s by themselves represent section labels within the
|
||||
configuration file. like this:
|
||||
|
||||
> [mysection]
|
||||
|
||||
Options are set using the "=" sign, for example
|
||||
|
||||
> myoption = value
|
||||
|
||||
Sometimes an option will have a number of discrete values which it can
|
||||
take. In that case, in the documentation, the options will be listed
|
||||
within square brackets (the "[" and "]" ones) separated by the pipe symbol
|
||||
("|"). For example:
|
||||
|
||||
> myoption = [value1|value2|value3]
|
||||
|
||||
means the option "myoption" can be assigned a value of "value1", "value2",
|
||||
or "value3".
|
||||
|
||||
Objects, or pseudo-objects are instantiated using the "=>" construct. For
|
||||
example:
|
||||
|
||||
> myobject => parameter
|
||||
|
||||
creates an object called "myobject" with some parameter whose definition
|
||||
would be specific to that object. Note that the config file parser
|
||||
considers "=>" and "=" to be equivalent and their use is purely to make
|
||||
configuration files more readable and easier to "humanly parse".
|
||||
|
||||
The comment character in Asterisk configuration files is the semicolon
|
||||
";". The reason it is not "#" is because the "#" symbol can be used as
|
||||
parts of extensions and it didn't seem like a good idea to have to escape
|
||||
it.
|
||||
|
||||
IAX CONFIGURATION IN ASTERISK
|
||||
-----------------------------
|
||||
|
||||
Like everything else in Asterisk, IAX's configuration lies in
|
||||
/etc/asterisk -- specifically /etc/asterisk/iax.conf
|
||||
|
||||
The IAX configuration file is a collection of sections, each of which
|
||||
(with the exception of the "general" section) represents an entity within
|
||||
the IAX scope.
|
||||
|
||||
------------
|
||||
|
||||
The first section is typically the "general" section. In this area,
|
||||
a number of parameters which affect the entire system are configured.
|
||||
Specifically, the default codecs, port and address, jitter behavior, TOS
|
||||
bits, and registrations.
|
||||
|
||||
The first line of the "general" section is always:
|
||||
|
||||
> [general]
|
||||
|
||||
Following the first line are a number of other possibilities:
|
||||
|
||||
> port = <portnum>
|
||||
|
||||
This sets the port that IAX will bind to. The default IAX port number is
|
||||
5036. It is recommended that this value not be altered in general.
|
||||
|
||||
> bindaddr = <ipaddr>
|
||||
|
||||
This allows you to bind IAX to a specific local IP address instead of
|
||||
binding to all addresses. This could be used to enhance security if, for
|
||||
example, you only wanted IAX to be available to users on your LAN.
|
||||
|
||||
> bandwidth = [low|medium|high]
|
||||
|
||||
The bandwidth selection initializes the codec selection to appropriate
|
||||
values for given bandwidths. The "high" selection enables all codecs and
|
||||
is recommended only for 10Mbps or higher connections. The "medium"
|
||||
bandwidth eliminates signed linear, Mu-law and A-law codecs, leaving only
|
||||
the codecs which are 32kbps and smaller (with MP3 as a special case). It
|
||||
can be used with broadband connections if desired. "low" eliminates ADPCM
|
||||
and MP3 formats, leaving only the G.723.1, GSM, and LPC10.
|
||||
|
||||
> allow = [gsm|lpc10|g723.1|adpcm|ulaw|alaw|mp3|slinear|all]
|
||||
> disallow = [gsm|lpc10|g723.1|adpcm|ulaw|alaw|mp3|slinear|all]
|
||||
|
||||
The "allow" and "disallow" allow you to fine tune the codec selection
|
||||
beyond the initial bandwidth selection on a codec-by-codec basis.
|
||||
|
||||
The recommended configuration is to select "low" bandwidth and then
|
||||
disallow the LPC10 codec just because it doesn't sound very good.
|
||||
|
||||
> jitterbuffer = [yes|no]
|
||||
> dropcount = <dropamount>
|
||||
> maxjitterbuffer = <max>
|
||||
> maxexcessbuffer = <max>
|
||||
|
||||
These parameters control the operation of the jitter buffer. The
|
||||
jitterbuffer should always be enabled unless you expect all your
|
||||
connections to be over a LAN. The drop count is the maximum number of
|
||||
voice packets to allow to drop (out of 100). Useful values are 3-10. The
|
||||
maxjitterbuffer is the maximum amount of jitter buffer to permit to be
|
||||
used. The "maxexcessbuffer" is the maximum amount of excess jitter buffer
|
||||
that is permitted before the jitter buffer is slowly shrunk to eliminate
|
||||
latency.
|
||||
|
||||
> accountcode = <code>
|
||||
> amaflags = [default|omit|billing|documentation]
|
||||
|
||||
These parameters affect call detail record generation. The first sets the
|
||||
account code for records received with IAX. The account code can be
|
||||
overridden on a per-user basis for incoming calls (see below). The
|
||||
amaflags controls how the record is labeled ("omit" causes no record to be
|
||||
written. "billing" and "documentation" label the records as billing or
|
||||
documentation records respectively, and "default" selects the system
|
||||
default.
|
||||
|
||||
> tos = [lowdelay|throughput|reliability|mincost|none]
|
||||
|
||||
IAX can optionally set the TOS (Type of Service) bits to specified values
|
||||
to help improve performance in routing. The recommended value is
|
||||
"lowdelay", which many routers (including any Linux routers with 2.4
|
||||
kernels that have not been altered with ip tables) will give priority to
|
||||
these packets, improving voice quality.
|
||||
|
||||
> register => <name>[:<secret>]@<host>[:port]
|
||||
|
||||
Any number of registery entries may be instantiated in the general
|
||||
section. Registration allows Asterisk to notify a remote Asterisk server
|
||||
(with a fixed address) what our current address is. In order for
|
||||
registration to work, the remote Asterisk server will need to have a
|
||||
dynamic peer entry with the same name (and secret if provided).
|
||||
|
||||
The name is a required field, and is the remote peer name that we wish to
|
||||
identify ourselves as. A secret may be provided as well. The secret is
|
||||
generally a shared password between the local server and the remote
|
||||
server. However, if the secret is in square brackets ([]'s) then it is
|
||||
interpreted as the name of a key to use. In that case, the local Asterisk
|
||||
server must have the *private* key (/var/lib/asterisk/keys/<name>.key) and
|
||||
the remote server will have to have the corresponding public key.
|
||||
|
||||
The "host" is a required field and is the hostname or IP address of the
|
||||
remote Asterisk server. The port specification is optional and is by
|
||||
default 5036 if not specified.
|
||||
|
||||
-------------
|
||||
|
||||
The following sections, after "general" define either users, peers or
|
||||
friends. A "user" is someone who connects to us. A "peer" is someone
|
||||
that we connect to. A "friend" is simply shorthand for creating a "user"
|
||||
and "peer" with identical parameters (i.e. someone who can contact us and
|
||||
who we contact).
|
||||
|
||||
> [identifier]
|
||||
|
||||
The section begins with the identifier in square brackets. The identifier
|
||||
should be an alphanumeric string.
|
||||
|
||||
> type = [user|peer|friend]
|
||||
|
||||
This line tells Asterisk how to interpret this entity. Users are things
|
||||
that connect to us, while peers are people we connect to, and a friend is
|
||||
shorthand for creating a user and a peer with identical information
|
||||
|
||||
----------------
|
||||
User fields:
|
||||
|
||||
> context = <context>
|
||||
|
||||
One or more context lines may be specified in a user, thus giving the user
|
||||
access to place calls in the given contexts. Contexts are used by
|
||||
Asterisk to divide dialing plans into logical units each with the ability
|
||||
to have numbers interpreted differently, have their own security model,
|
||||
auxilliary switch handling, and include other contexts. Most users are
|
||||
given access to the default context. Trusted users could be given access
|
||||
to the local context for example.
|
||||
|
||||
> permit = <ipaddr>/<netmask>
|
||||
> deny = <ipaddr>/<netmask>
|
||||
|
||||
Permit and deny rules may be applied to users, allowing them to connect
|
||||
from certain IP addresses and not others. The permit and deny rules are
|
||||
interpreted in sequence and all are evaluated on a given IP address, with
|
||||
the final result being the decision. For example:
|
||||
|
||||
> permit = 0.0.0.0/0.0.0.0
|
||||
> deny = 192.168.0.0/255.255.255.0
|
||||
|
||||
would deny anyone in 192.168.0.0 with a netmask of 24 bits (class C),
|
||||
whereas:
|
||||
|
||||
> deny = 192.168.0.0/255.255.255.0
|
||||
> permit = 0.0.0.0/0.0.0.0
|
||||
|
||||
would not deny anyone since the final rule would permit anyone, thsu
|
||||
overriding the denial.
|
||||
|
||||
If no permit/deny rules are listed, it is assumed that someone may connect
|
||||
from anywhere.
|
||||
|
||||
> callerid = <callerid>
|
||||
|
||||
You may override the Caller*ID information passed by a user to you (if
|
||||
they choose to send it) in order that it always be accurate from the
|
||||
perspective of your server.
|
||||
|
||||
> auth = [md5|plaintext|rsa]
|
||||
|
||||
You may select which authentication methods are permitted to be used by
|
||||
the user to authenticate to us. Multiple methods may be specified,
|
||||
separated by commas. If md5 or plaintext authentication is selected, a
|
||||
secret must be provided. If RSA authentication is specified, then one or
|
||||
more key names must be specifed with "inkeys"
|
||||
|
||||
If no secret is specified and no authentication method is specified, then
|
||||
no authentication will be required.
|
||||
|
||||
> secret = <secret>
|
||||
|
||||
The "secret" line specifies the shared secret for md5 and plaintext
|
||||
authentication methods. It is never suggested to use plaintext except in
|
||||
some cases for debugging.
|
||||
|
||||
> inkeys = key1[:key2...]
|
||||
|
||||
The "inkeys" line specifies which keys we can use to authenticate the
|
||||
remote peer. If the peer's challenge passes with any of the given keys,
|
||||
then we accept its authentication. The key files live in
|
||||
/var/lib/asterisk/keys/<name>.pub and are *public keys*. Public keys are
|
||||
not typically DES3 encrypted and thus do not usually need initialization.
|
||||
|
||||
---------------
|
||||
Peer configuration
|
||||
|
||||
> allow = [gsm|lpc10|g723.1|adpcm|ulaw|alaw|mp3|slinear|all]
|
||||
> disallow = [gsm|lpc10|g723.1|adpcm|ulaw|alaw|mp3|slinear|all]
|
||||
|
||||
The "allow" and "disallow" may be used to enable or disable specific codec
|
||||
support on a per-peer basis.
|
||||
|
||||
> host = [<ipaddr>|dynamic]
|
||||
|
||||
The host line specifies the hostname or IP address of the remote host, or
|
||||
may be the word "dynamic" signifying that the host will register with us
|
||||
(see register => in the general section above).
|
||||
|
||||
> defaultip = <ipaddr>
|
||||
|
||||
If the host uses dynamic registration, Asterisk may still be given a
|
||||
default IP address to use when dynamic registration has not been performed
|
||||
or has timed out.
|
||||
|
||||
|
||||
3
SECURITY
3
SECURITY
@@ -36,3 +36,6 @@ include => default
|
||||
exten => 6123,Dial,Tor/1
|
||||
|
||||
|
||||
DON'T FORGET TO TAKE THE DEMO CONTEXT OUT OF YOUR DEFAULT CONTEXT. There
|
||||
isn't really a security reason, it just will keep people from wanting to
|
||||
play with your asterisk setup remotely.
|
||||
|
||||
116
acl.c
Normal file
116
acl.c
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Various sorts of access control
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <asterisk/acl.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#define AST_SENSE_DENY 0
|
||||
#define AST_SENSE_ALLOW 1
|
||||
|
||||
struct ast_ha {
|
||||
/* Host access rule */
|
||||
struct in_addr netaddr;
|
||||
struct in_addr netmask;
|
||||
int sense;
|
||||
struct ast_ha *next;
|
||||
};
|
||||
|
||||
void ast_free_ha(struct ast_ha *ha)
|
||||
{
|
||||
struct ast_ha *hal;
|
||||
while(ha) {
|
||||
hal = ha;
|
||||
ha = ha->next;
|
||||
free(hal);
|
||||
}
|
||||
}
|
||||
|
||||
struct ast_ha *ast_append_ha(char *sense, char *stuff, struct ast_ha *path)
|
||||
{
|
||||
struct ast_ha *ha = malloc(sizeof(struct ast_ha));
|
||||
char *nm;
|
||||
struct ast_ha *prev = NULL;
|
||||
struct ast_ha *ret;
|
||||
ret = path;
|
||||
while(path) {
|
||||
prev = path;
|
||||
path = path->next;
|
||||
}
|
||||
if (ha) {
|
||||
strtok(stuff, "/");
|
||||
nm = strtok(NULL, "/");
|
||||
if (!nm)
|
||||
nm = "255.255.255.255";
|
||||
if (!inet_aton(stuff, &ha->netaddr)) {
|
||||
ast_log(LOG_WARNING, "%s not a valid IP\n", stuff);
|
||||
free(ha);
|
||||
return NULL;
|
||||
}
|
||||
if (!inet_aton(nm, &ha->netmask)) {
|
||||
ast_log(LOG_WARNING, "%s not a valid netmask\n", nm);
|
||||
free(ha);
|
||||
return NULL;
|
||||
}
|
||||
ha->netaddr.s_addr &= ha->netmask.s_addr;
|
||||
if (!strncasecmp(sense, "p", 1)) {
|
||||
ha->sense = AST_SENSE_ALLOW;
|
||||
} else {
|
||||
ha->sense = AST_SENSE_DENY;
|
||||
}
|
||||
ha->next = NULL;
|
||||
if (prev)
|
||||
prev->next = ha;
|
||||
else
|
||||
ret = ha;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int ast_apply_ha(struct ast_ha *ha, struct sockaddr_in *sin)
|
||||
{
|
||||
/* Start optimistic */
|
||||
int res = AST_SENSE_ALLOW;
|
||||
while(ha) {
|
||||
/* For each rule, if this address and the netmask = the net address
|
||||
apply the current rule */
|
||||
if ((sin->sin_addr.s_addr & ha->netmask.s_addr) == (ha->netaddr.s_addr))
|
||||
res = ha->sense;
|
||||
ha = ha->next;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int ast_get_ip(struct sockaddr_in *sin, char *value)
|
||||
{
|
||||
struct hostent *hp;
|
||||
hp = gethostbyname(value);
|
||||
if (hp) {
|
||||
memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr));
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Unable to lookup '%s'\n", value);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
85
alaw.c
Normal file
85
alaw.c
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* u-Law to Signed linear conversion
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/alaw.h>
|
||||
|
||||
#define AMI_MASK 0x55
|
||||
|
||||
static inline unsigned char linear2alaw (short int linear)
|
||||
{
|
||||
int mask;
|
||||
int seg;
|
||||
int pcm_val;
|
||||
static int seg_end[8] =
|
||||
{
|
||||
0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF
|
||||
};
|
||||
|
||||
pcm_val = linear;
|
||||
if (pcm_val >= 0)
|
||||
{
|
||||
/* Sign (7th) bit = 1 */
|
||||
mask = AMI_MASK | 0x80;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Sign bit = 0 */
|
||||
mask = AMI_MASK;
|
||||
pcm_val = -pcm_val;
|
||||
}
|
||||
|
||||
/* Convert the scaled magnitude to segment number. */
|
||||
for (seg = 0; seg < 8; seg++)
|
||||
{
|
||||
if (pcm_val <= seg_end[seg])
|
||||
break;
|
||||
}
|
||||
/* Combine the sign, segment, and quantization bits. */
|
||||
return ((seg << 4) | ((pcm_val >> ((seg) ? (seg + 3) : 4)) & 0x0F)) ^ mask;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static inline short int alaw2linear (unsigned char alaw)
|
||||
{
|
||||
int i;
|
||||
int seg;
|
||||
|
||||
alaw ^= AMI_MASK;
|
||||
i = ((alaw & 0x0F) << 4);
|
||||
seg = (((int) alaw & 0x70) >> 4);
|
||||
if (seg)
|
||||
i = (i + 0x100) << (seg - 1);
|
||||
return (short int) ((alaw & 0x80) ? i : -i);
|
||||
}
|
||||
|
||||
unsigned char __ast_lin2a[8192];
|
||||
short __ast_alaw[256];
|
||||
|
||||
void ast_alaw_init(void)
|
||||
{
|
||||
int i;
|
||||
/*
|
||||
* Set up mu-law conversion table
|
||||
*/
|
||||
for(i = 0;i < 256;i++)
|
||||
{
|
||||
__ast_alaw[i] = alaw2linear(i);
|
||||
}
|
||||
/* set up the reverse (mu-law) conversion table */
|
||||
for(i = -32768; i < 32768; i++)
|
||||
{
|
||||
__ast_lin2a[((unsigned short)i) >> 3] = linear2alaw(i);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,9 +11,13 @@
|
||||
# the GNU General Public License
|
||||
#
|
||||
|
||||
#APPS=app_dial.so app_playback.so app_directory.so app_intercom.so app_mp3.so
|
||||
APPS=app_dial.so app_playback.so app_voicemail.so app_directory.so app_intercom.so app_mp3.so \
|
||||
app_system.so app_echo.so app_record.so app_image.so app_url.so app_disa.so \
|
||||
app_agi.so
|
||||
app_agi.so app_qcall.so app_adsiprog.so app_getcpeid.so app_milliwatt.so \
|
||||
app_zapateller.so
|
||||
|
||||
APPS+=$(shell if [ -f /usr/include/zap.h ]; then echo "app_zapras.so app_meetme.so" ; fi)
|
||||
|
||||
CFLAGS+=
|
||||
|
||||
|
||||
1567
apps/app_adsiprog.c
Normal file
1567
apps/app_adsiprog.c
Normal file
File diff suppressed because it is too large
Load Diff
122
apps/app_agi.c
122
apps/app_agi.c
@@ -161,6 +161,21 @@ static void setup_env(struct ast_channel *chan, char *request, int fd)
|
||||
fdprintf(fd, "\n");
|
||||
}
|
||||
|
||||
static int handle_answer(struct ast_channel *chan, int fd, int argc, char *argv[])
|
||||
{
|
||||
int res;
|
||||
res = 0;
|
||||
if (chan->state != AST_STATE_UP) {
|
||||
/* Answer the chan */
|
||||
res = ast_answer(chan);
|
||||
}
|
||||
fdprintf(fd, "200 result=%d\n", res);
|
||||
if (res >= 0)
|
||||
return RESULT_SUCCESS;
|
||||
else
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
|
||||
static int handle_waitfordigit(struct ast_channel *chan, int fd, int argc, char *argv[])
|
||||
{
|
||||
int res;
|
||||
@@ -182,6 +197,13 @@ static int handle_sendtext(struct ast_channel *chan, int fd, int argc, char *arg
|
||||
int res;
|
||||
if (argc != 3)
|
||||
return RESULT_SHOWUSAGE;
|
||||
/* At the moment, the parser (perhaps broken) returns with
|
||||
the last argument PLUS the newline at the end of the input
|
||||
buffer. This probably needs to be fixed, but I wont do that
|
||||
because other stuff may break as a result. The right way
|
||||
would probably be to strip off the trailing newline before
|
||||
parsing, then here, add a newline at the end of the string
|
||||
before sending it to ast_sendtext --DUDE */
|
||||
res = ast_sendtext(chan, argv[2]);
|
||||
fdprintf(fd, "200 result=%d\n", res);
|
||||
if (res >= 0)
|
||||
@@ -190,13 +212,49 @@ static int handle_sendtext(struct ast_channel *chan, int fd, int argc, char *arg
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
|
||||
static int handle_recvchar(struct ast_channel *chan, int fd, int argc, char *argv[])
|
||||
{
|
||||
int res;
|
||||
if (argc != 3)
|
||||
return RESULT_SHOWUSAGE;
|
||||
res = ast_recvchar(chan,atoi(argv[2]));
|
||||
if (res == 0) {
|
||||
fdprintf(fd, "200 result=%d (timeout)\n", res);
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
if (res > 0) {
|
||||
fdprintf(fd, "200 result=%d\n", res);
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
else {
|
||||
fdprintf(fd, "200 result=%d (hangup)\n", res);
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
static int handle_tddmode(struct ast_channel *chan, int fd, int argc, char *argv[])
|
||||
{
|
||||
int res,x;
|
||||
if (argc != 3)
|
||||
return RESULT_SHOWUSAGE;
|
||||
if (!strncasecmp(argv[2],"on",2)) x = 1; else x = 0;
|
||||
if (!strncasecmp(argv[2],"mate",4)) x = 2;
|
||||
if (!strncasecmp(argv[2],"tdd",3)) x = 1;
|
||||
res = ast_channel_setoption(chan,AST_OPTION_TDD,&x,sizeof(char),0);
|
||||
fdprintf(fd, "200 result=%d\n", res);
|
||||
if (res >= 0)
|
||||
return RESULT_SUCCESS;
|
||||
else
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
|
||||
static int handle_sendimage(struct ast_channel *chan, int fd, int argc, char *argv[])
|
||||
{
|
||||
int res;
|
||||
if (argc != 3)
|
||||
return RESULT_SHOWUSAGE;
|
||||
res = ast_send_image(chan, argv[2]);
|
||||
if (!chan->softhangup)
|
||||
if (!ast_check_hangup(chan))
|
||||
res = 0;
|
||||
fdprintf(fd, "200 result=%d\n", res);
|
||||
if (res >= 0)
|
||||
@@ -219,7 +277,7 @@ static int handle_streamfile(struct ast_channel *chan, int fd, int argc, char *a
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
res = ast_waitstream(chan, argv[3]);
|
||||
|
||||
ast_stopstream(chan);
|
||||
fdprintf(fd, "200 result=%d\n", res);
|
||||
if (res >= 0)
|
||||
return RESULT_SUCCESS;
|
||||
@@ -235,7 +293,23 @@ static int handle_saynumber(struct ast_channel *chan, int fd, int argc, char *ar
|
||||
return RESULT_SHOWUSAGE;
|
||||
if (sscanf(argv[2], "%i", &num) != 1)
|
||||
return RESULT_SHOWUSAGE;
|
||||
res = ast_say_number(chan, num, chan->language);
|
||||
res = ast_say_number(chan, num, AST_DIGIT_ANY, chan->language);
|
||||
fdprintf(fd, "200 result=%d\n", res);
|
||||
if (res >= 0)
|
||||
return RESULT_SUCCESS;
|
||||
else
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
|
||||
static int handle_saydigits(struct ast_channel *chan, int fd, int argc, char *argv[])
|
||||
{
|
||||
int res;
|
||||
int num;
|
||||
if (argc != 4)
|
||||
return RESULT_SHOWUSAGE;
|
||||
if (sscanf(argv[2], "%i", &num) != 1)
|
||||
return RESULT_SHOWUSAGE;
|
||||
res = ast_say_digit_str(chan, argv[2], AST_DIGIT_ANY, chan->language);
|
||||
fdprintf(fd, "200 result=%d\n", res);
|
||||
if (res >= 0)
|
||||
return RESULT_SUCCESS;
|
||||
@@ -272,7 +346,7 @@ static int handle_setcontext(struct ast_channel *chan, int fd, int argc, char *a
|
||||
|
||||
if (argc != 3)
|
||||
return RESULT_SHOWUSAGE;
|
||||
strncpy(chan->context, argv[2], sizeof(chan->context));
|
||||
strncpy(chan->context, argv[2], sizeof(chan->context)-1);
|
||||
fdprintf(fd, "200 result=0\n");
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
@@ -281,7 +355,7 @@ static int handle_setextension(struct ast_channel *chan, int fd, int argc, char
|
||||
{
|
||||
if (argc != 3)
|
||||
return RESULT_SHOWUSAGE;
|
||||
strncpy(chan->exten, argv[2], sizeof(chan->exten));
|
||||
strncpy(chan->exten, argv[2], sizeof(chan->exten)-1);
|
||||
fdprintf(fd, "200 result=0\n");
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
@@ -435,6 +509,11 @@ static int handle_recordfile(struct ast_channel *chan, int fd, int argc, char *a
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static char usage_answer[] =
|
||||
" Usage: ANSWER\n"
|
||||
" Answers channel if not already in answer state. Returns -1 on\n"
|
||||
" channel failure, or 0 if successful.\n";
|
||||
|
||||
static char usage_waitfordigit[] =
|
||||
" Usage: WAIT FOR DIGIT <timeout>\n"
|
||||
" Waits up to 'timeout' seconds for channel to receive a DTMF digit.\n"
|
||||
@@ -450,6 +529,19 @@ static char usage_sendtext[] =
|
||||
" consisting of greater than one word should be placed in quotes since the\n"
|
||||
" command only accepts a single argument.\n";
|
||||
|
||||
static char usage_recvchar[] =
|
||||
" Usage: RECEIVE CHAR <timeout>\n"
|
||||
" Receives a character of text on a channel. Specify timeout to be the\n"
|
||||
" maximum time to wait for input in milliseconds, or 0 for infinite. Most channels\n"
|
||||
" do not support the reception of text. Returns the decimal value of the character\n"
|
||||
" if one is received, or 0 if the channel does not support text reception. Returns\n"
|
||||
" -1 only on error/hangup.\n";
|
||||
|
||||
static char usage_tddmode[] =
|
||||
" Usage: TDD MODE <on|off>\n"
|
||||
" Enable/Disable TDD transmission/reception on a channel. Returns 1 if\n"
|
||||
" successful, or 0 if channel is not TDD-capable.\n";
|
||||
|
||||
static char usage_sendimage[] =
|
||||
" Usage: SEND IMAGE <image>\n"
|
||||
" Sends the given image on a channel. Most channels do not support the\n"
|
||||
@@ -473,6 +565,13 @@ static char usage_saynumber[] =
|
||||
" being pressed, or the ASCII numerical value of the digit if one was pressed or\n"
|
||||
" -1 on error/hangup.\n";
|
||||
|
||||
static char usage_saydigits[] =
|
||||
" Usage: SAY DIGITS <number> <escape digits>\n"
|
||||
" Say a given digit string, returning early if any of the given DTMF digits\n"
|
||||
" are received on the channel. Returns 0 if playback completes without a digit\n"
|
||||
" being pressed, or the ASCII numerical value of the digit if one was pressed or\n"
|
||||
" -1 on error/hangup.\n";
|
||||
|
||||
static char usage_getdata[] =
|
||||
" Usage: GET DATA <file to be streamed> [timeout] [max digits]\n"
|
||||
" Stream the given file, and recieve DTMF data. Returns the digits recieved\n"
|
||||
@@ -498,10 +597,15 @@ static char usage_recordfile[] =
|
||||
" -1 for no timeout\n";
|
||||
|
||||
agi_command commands[] = {
|
||||
{ { "answer", NULL }, handle_answer, "Asserts answer", usage_answer },
|
||||
{ { "answer\n", NULL }, handle_answer, "Asserts answer", usage_answer },
|
||||
{ { "wait", "for", "digit", NULL }, handle_waitfordigit, "Waits for a digit to be pressed", usage_waitfordigit },
|
||||
{ { "send", "text", NULL }, handle_sendtext, "Sends text to channels supporting it", usage_sendtext },
|
||||
{ { "receive", "char", NULL }, handle_recvchar, "Receives text from channels supporting it", usage_recvchar },
|
||||
{ { "tdd", "mode", NULL }, handle_tddmode, "Sends text to channels supporting it", usage_tddmode },
|
||||
{ { "stream", "file", NULL }, handle_streamfile, "Sends audio file on channel", usage_streamfile },
|
||||
{ { "send", "image", NULL }, handle_sendimage, "Sends images to channels supporting it", usage_sendimage },
|
||||
{ { "say", "digits", NULL }, handle_saydigits, "Says a given digit string", usage_saydigits },
|
||||
{ { "say", "number", NULL }, handle_saynumber, "Says a given number", usage_saynumber },
|
||||
{ { "get", "data", NULL }, handle_getdata, "Gets data on a channel", usage_getdata },
|
||||
{ { "set", "context", NULL }, handle_setcontext, "Sets channel context", usage_setcontext },
|
||||
@@ -677,6 +781,10 @@ static int run_agi(struct ast_channel *chan, char *request, int *fds, int pid)
|
||||
pid = -1;
|
||||
break;
|
||||
}
|
||||
/* get rid of trailing newline, if any */
|
||||
if (*buf && buf[strlen(buf) - 1] == '\n')
|
||||
buf[strlen(buf) - 1] = 0;
|
||||
|
||||
returnstatus |= agi_handle_command(chan, fds[1], buf);
|
||||
/* If the handle_command returns -1, we need to stop */
|
||||
if (returnstatus < 0) {
|
||||
@@ -709,13 +817,14 @@ static int agi_exec(struct ast_channel *chan, void *data)
|
||||
}
|
||||
|
||||
|
||||
strncpy(tmp, data, sizeof(tmp));
|
||||
strncpy(tmp, data, sizeof(tmp)-1);
|
||||
strtok(tmp, "|");
|
||||
args = strtok(NULL, "|");
|
||||
ringy = strtok(NULL,"|");
|
||||
if (!args)
|
||||
args = "";
|
||||
LOCAL_USER_ADD(u);
|
||||
#if 0
|
||||
/* Answer if need be */
|
||||
if (chan->state != AST_STATE_UP) {
|
||||
if (ringy) { /* if for ringing first */
|
||||
@@ -728,6 +837,7 @@ static int agi_exec(struct ast_channel *chan, void *data)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
res = launch_script(tmp, args, fds, &pid);
|
||||
if (!res) {
|
||||
res = run_agi(chan, tmp, fds, pid);
|
||||
|
||||
470
apps/app_dial.c
470
apps/app_dial.c
@@ -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>
|
||||
@@ -19,6 +20,8 @@
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/say.h>
|
||||
#include <asterisk/parking.h>
|
||||
#include <asterisk/musiconhold.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
@@ -31,18 +34,14 @@
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Dialing/Parking Application";
|
||||
static char *tdesc = "Dialing Application";
|
||||
|
||||
static char *app = "Dial";
|
||||
|
||||
static char *parkedcall = "ParkedCall";
|
||||
|
||||
static char *synopsis = "Place an call and connect to the current channel";
|
||||
|
||||
static char *registrar = "app_dial";
|
||||
|
||||
static char *descrip =
|
||||
" Dial(Technology/resource[&Technology2/resource2...][|timeout][|transfer]):\n"
|
||||
" Dial(Technology/resource[&Technology2/resource2...][|timeout][|options]):\n"
|
||||
"Requests one or more channels and places specified outgoing calls on them.\n"
|
||||
"As soon as a channel answers, the Dial app will answer the originating\n"
|
||||
"channel (if it needs to be answered) and will bridge a call with the channel\n"
|
||||
@@ -57,26 +56,14 @@ static char *descrip =
|
||||
"no-answer).\n"
|
||||
" This application returns -1 if the originating channel hangs up, or if the\n"
|
||||
"call is bridged and either of the parties in the bridge terminate the call.\n"
|
||||
"The transfer string may contain a 't' to allow the called user transfer a\n"
|
||||
"call or 'T' to allow the calling user to transfer the call.\n"
|
||||
"The option string may contain zero or more of the following characters:\n"
|
||||
" 't' -- allow the called user transfer the calling user\n"
|
||||
" 'T' -- to allow the calling user to transfer the call.\n"
|
||||
" 'r' -- indicate ringing to the calling party, pass no audio until answered.\n"
|
||||
" 'm' -- provide hold music to the calling party until answered.\n"
|
||||
" In addition to transferring the call, a call may be parked and then picked\n"
|
||||
"up by another user.\n";
|
||||
|
||||
/* No more than 45 seconds parked before you do something with them */
|
||||
static int parkingtime = 45000;
|
||||
|
||||
/* Context for which parking is made accessible */
|
||||
static char parking_con[AST_MAX_EXTENSION] = "parkedcalls";
|
||||
|
||||
/* Extension you type to park the call */
|
||||
static char parking_ext[AST_MAX_EXTENSION] = "700";
|
||||
|
||||
/* First available extension for parking */
|
||||
static int parking_start = 701;
|
||||
|
||||
/* Last available extension for parking */
|
||||
static int parking_stop = 750;
|
||||
|
||||
/* We define a customer "local user" structure because we
|
||||
use it not only for keeping track of what is in use but
|
||||
also for keeping track of who we're dialing. */
|
||||
@@ -85,177 +72,13 @@ struct localuser {
|
||||
struct ast_channel *chan;
|
||||
int stillgoing;
|
||||
int allowredirect;
|
||||
int ringbackonly;
|
||||
int musiconhold;
|
||||
struct localuser *next;
|
||||
};
|
||||
|
||||
struct parkeduser {
|
||||
struct ast_channel *chan;
|
||||
struct timeval start;
|
||||
int parkingnum;
|
||||
/* Where to go if our parking time expires */
|
||||
char context[AST_MAX_EXTENSION];
|
||||
char exten[AST_MAX_EXTENSION];
|
||||
int priority;
|
||||
struct parkeduser *next;
|
||||
};
|
||||
|
||||
static struct parkeduser *parkinglot;
|
||||
|
||||
static pthread_mutex_t parking_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
static pthread_t parking_thread;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int bridge_call(struct ast_channel *chan, struct ast_channel *peer, int allowredirect);
|
||||
|
||||
|
||||
static int park_call(struct ast_channel *chan, struct ast_channel *peer)
|
||||
{
|
||||
/* We put the user in the parking list, then wake up the parking thread to be sure it looks
|
||||
after these channels too */
|
||||
struct parkeduser *pu, *cur;
|
||||
int x;
|
||||
pu = malloc(sizeof(struct parkeduser));
|
||||
if (pu) {
|
||||
ast_pthread_mutex_lock(&parking_lock);
|
||||
for (x=parking_start;x<=parking_stop;x++) {
|
||||
cur = parkinglot;
|
||||
while(cur) {
|
||||
if (cur->parkingnum == x)
|
||||
break;
|
||||
cur = cur->next;
|
||||
}
|
||||
if (!cur)
|
||||
break;
|
||||
}
|
||||
if (x <= parking_stop) {
|
||||
pu->chan = chan;
|
||||
gettimeofday(&pu->start, NULL);
|
||||
pu->parkingnum = x;
|
||||
/* Remember what had been dialed, so that if the parking
|
||||
expires, we try to come back to the same place */
|
||||
strncpy(pu->context, chan->context, sizeof(pu->context));
|
||||
strncpy(pu->exten, chan->exten, sizeof(pu->exten));
|
||||
pu->priority = chan->priority;
|
||||
pu->next = parkinglot;
|
||||
parkinglot = pu;
|
||||
ast_pthread_mutex_unlock(&parking_lock);
|
||||
/* Wake up the (presumably select()ing) thread */
|
||||
pthread_kill(parking_thread, SIGURG);
|
||||
if (option_verbose > 1)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "Parked %s on %d\n", pu->chan->name, pu->parkingnum);
|
||||
ast_say_digits(peer, pu->parkingnum, peer->language);
|
||||
return 0;
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "No more parking spaces\n");
|
||||
free(pu);
|
||||
ast_pthread_mutex_unlock(&parking_lock);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Out of memory\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *do_parking_thread(void *ignore)
|
||||
{
|
||||
int ms, tms, max;
|
||||
struct parkeduser *pu, *pl, *pt = NULL;
|
||||
struct timeval tv;
|
||||
struct ast_frame *f;
|
||||
int x;
|
||||
fd_set rfds, efds;
|
||||
fd_set nrfds, nefds;
|
||||
FD_ZERO(&rfds);
|
||||
FD_ZERO(&efds);
|
||||
for (;;) {
|
||||
ms = -1;
|
||||
max = -1;
|
||||
ast_pthread_mutex_lock(&parking_lock);
|
||||
pl = NULL;
|
||||
pu = parkinglot;
|
||||
gettimeofday(&tv, NULL);
|
||||
FD_ZERO(&nrfds);
|
||||
FD_ZERO(&nefds);
|
||||
while(pu) {
|
||||
tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
|
||||
if (tms > parkingtime) {
|
||||
/* They've been waiting too long, send them back to where they came. Theoretically they
|
||||
should have their original extensions and such, but we copy to be on the safe side */
|
||||
strncpy(pu->chan->exten, pu->exten, sizeof(pu->chan->exten));
|
||||
strncpy(pu->chan->context, pu->context, sizeof(pu->chan->context));
|
||||
pu->chan->priority = pu->priority;
|
||||
/* Start up the PBX, or hang them up */
|
||||
if (ast_pbx_start(pu->chan)) {
|
||||
ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", pu->chan->name);
|
||||
ast_hangup(pu->chan);
|
||||
}
|
||||
/* And take them out of the parking lot */
|
||||
if (pl)
|
||||
pl->next = pu->next;
|
||||
else
|
||||
parkinglot = pu->next;
|
||||
pt = pu;
|
||||
pu = pu->next;
|
||||
free(pt);
|
||||
} else {
|
||||
for (x=0;x<AST_MAX_FDS;x++) {
|
||||
if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
|
||||
if (FD_ISSET(pu->chan->fds[x], &efds))
|
||||
pu->chan->exception = 1;
|
||||
pu->chan->fdno = x;
|
||||
/* See if they need servicing */
|
||||
f = ast_read(pu->chan);
|
||||
if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
|
||||
/* There's a problem, hang them up*/
|
||||
if (option_verbose > 1)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being parked\n", pu->chan->name);
|
||||
ast_hangup(pu->chan);
|
||||
/* And take them out of the parking lot */
|
||||
if (pl)
|
||||
pl->next = pu->next;
|
||||
else
|
||||
parkinglot = pu->next;
|
||||
pt = pu;
|
||||
pu = pu->next;
|
||||
free(pt);
|
||||
break;
|
||||
} else {
|
||||
/* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
|
||||
ast_frfree(f);
|
||||
goto std; /* XXX Ick: jumping into an else statement??? XXX */
|
||||
}
|
||||
}
|
||||
}
|
||||
if (x >= AST_MAX_FDS) {
|
||||
/* Keep this one for next one */
|
||||
std: FD_SET(pu->chan->fds[x], &nrfds);
|
||||
FD_SET(pu->chan->fds[x], &nefds);
|
||||
/* Keep track of our longest wait */
|
||||
if ((tms < ms) || (ms < 0))
|
||||
ms = tms;
|
||||
if (pu->chan->fds[x] > max)
|
||||
max = pu->chan->fds[x];
|
||||
pl = pu;
|
||||
pu = pu->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
ast_pthread_mutex_unlock(&parking_lock);
|
||||
rfds = nrfds;
|
||||
efds = nefds;
|
||||
tv.tv_sec = ms / 1000;
|
||||
tv.tv_usec = (ms % 1000) * 1000;
|
||||
/* Wait for something to happen */
|
||||
select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
|
||||
pthread_testcancel();
|
||||
}
|
||||
return NULL; /* Never reached */
|
||||
}
|
||||
|
||||
static void hanguptree(struct localuser *outgoing, struct ast_channel *exception)
|
||||
{
|
||||
/* Hang up a tree of stuff */
|
||||
@@ -285,6 +108,8 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
|
||||
struct ast_channel *watchers[MAX];
|
||||
int pos;
|
||||
int single;
|
||||
int moh=0;
|
||||
int ringind=0;
|
||||
struct ast_channel *winner;
|
||||
|
||||
single = (outgoing && !outgoing->next);
|
||||
@@ -294,6 +119,16 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
|
||||
ast_channel_make_compatible(outgoing->chan, in);
|
||||
}
|
||||
|
||||
if (outgoing) {
|
||||
moh = outgoing->musiconhold;
|
||||
ringind = outgoing->ringbackonly;
|
||||
if (outgoing->musiconhold) {
|
||||
ast_moh_start(in, NULL);
|
||||
} else if (outgoing->ringbackonly) {
|
||||
ast_indicate(in, AST_CONTROL_RINGING);
|
||||
}
|
||||
}
|
||||
|
||||
while(*to && !peer) {
|
||||
o = outgoing;
|
||||
found = -1;
|
||||
@@ -344,12 +179,16 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "%s is busy\n", o->chan->name);
|
||||
o->stillgoing = 0;
|
||||
if (in->cdr)
|
||||
ast_cdr_busy(in->cdr);
|
||||
numbusies++;
|
||||
break;
|
||||
case AST_CONTROL_CONGESTION:
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "%s is circuit-busy\n", o->chan->name);
|
||||
o->stillgoing = 0;
|
||||
if (in->cdr)
|
||||
ast_cdr_busy(in->cdr);
|
||||
numbusies++;
|
||||
break;
|
||||
case AST_CONTROL_RINGING:
|
||||
@@ -366,10 +205,12 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
|
||||
default:
|
||||
ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass);
|
||||
}
|
||||
} else if (single && (f->frametype == AST_FRAME_VOICE)) {
|
||||
} else if (single && (f->frametype == AST_FRAME_VOICE) &&
|
||||
!(outgoing->ringbackonly || outgoing->musiconhold)) {
|
||||
if (ast_write(in, f))
|
||||
ast_log(LOG_WARNING, "Unable to forward frame\n");
|
||||
} else if (single && (f->frametype == AST_FRAME_IMAGE)) {
|
||||
} else if (single && (f->frametype == AST_FRAME_IMAGE) &&
|
||||
!(outgoing->ringbackonly || outgoing->musiconhold)) {
|
||||
if (ast_write(in, f))
|
||||
ast_log(LOG_WARNING, "Unable to forward image\n");
|
||||
}
|
||||
@@ -397,181 +238,16 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
|
||||
if (!*to && (option_verbose > 2))
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig);
|
||||
}
|
||||
if (moh) {
|
||||
ast_moh_stop(in);
|
||||
} else if (ringind) {
|
||||
ast_indicate(in, -1);
|
||||
}
|
||||
|
||||
return peer;
|
||||
|
||||
}
|
||||
|
||||
static int bridge_call(struct ast_channel *chan, struct ast_channel *peer, int allowredirect)
|
||||
{
|
||||
/* Copy voice back and forth between the two channels. Give the peer
|
||||
the ability to transfer calls with '#<extension' syntax. */
|
||||
int len;
|
||||
struct ast_frame *f;
|
||||
struct ast_channel *who;
|
||||
char newext[256], *ptr;
|
||||
int res;
|
||||
struct ast_option_header *aoh;
|
||||
/* Answer if need be */
|
||||
if (chan->state != AST_STATE_UP) {
|
||||
if (ast_answer(chan))
|
||||
return -1;
|
||||
}
|
||||
peer->appl = "Bridged Call";
|
||||
peer->data = chan->name;
|
||||
for (;;) {
|
||||
res = ast_channel_bridge(chan, peer, allowredirect ? AST_BRIDGE_DTMF_CHANNEL_1 : 0, &f, &who);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!f || ((f->frametype == AST_FRAME_CONTROL) && ((f->subclass == AST_CONTROL_HANGUP) || (f->subclass == AST_CONTROL_BUSY) ||
|
||||
(f->subclass == AST_CONTROL_CONGESTION)))) {
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RINGING)) {
|
||||
if (who == chan)
|
||||
ast_indicate(peer, AST_CONTROL_RINGING);
|
||||
else
|
||||
ast_indicate(chan, AST_CONTROL_RINGING);
|
||||
}
|
||||
if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_OPTION)) {
|
||||
aoh = f->data;
|
||||
/* Forward option Requests */
|
||||
if (aoh && (aoh->flag == AST_OPTION_FLAG_REQUEST)) {
|
||||
if (who == chan)
|
||||
ast_channel_setoption(peer, ntohs(aoh->option), aoh->data, f->datalen - sizeof(struct ast_option_header), 0);
|
||||
else
|
||||
ast_channel_setoption(chan, ntohs(aoh->option), aoh->data, f->datalen - sizeof(struct ast_option_header), 0);
|
||||
}
|
||||
}
|
||||
if ((f->frametype == AST_FRAME_DTMF) && (who == peer) && allowredirect &&
|
||||
(f->subclass == '#')) {
|
||||
memset(newext, 0, sizeof(newext));
|
||||
ptr = newext;
|
||||
/* Transfer */
|
||||
if ((res=ast_streamfile(peer, "pbx-transfer", chan->language)))
|
||||
break;
|
||||
if ((res=ast_waitstream(peer, AST_DIGIT_ANY)) < 0)
|
||||
break;
|
||||
ast_stopstream(peer);
|
||||
if (res > 0) {
|
||||
/* If they've typed a digit already, handle it */
|
||||
newext[0] = res;
|
||||
ptr++;
|
||||
len --;
|
||||
}
|
||||
res = 0;
|
||||
while(strlen(newext) < sizeof(newext - 1)) {
|
||||
res = ast_waitfordigit(peer, 3000);
|
||||
if (res < 1)
|
||||
break;
|
||||
*(ptr++) = res;
|
||||
if (!ast_canmatch_extension(peer, peer->context, newext, 1, peer->callerid) ||
|
||||
ast_exists_extension(peer, peer->context, newext, 1, peer->callerid)) {
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (res)
|
||||
break;
|
||||
if (!strcmp(newext, parking_ext)) {
|
||||
if (!park_call(chan, peer)) {
|
||||
/* We return non-zero, but tell the PBX not to hang the channel when
|
||||
the thread dies -- We have to be careful now though. We are responsible for
|
||||
hanging up the channel, else it will never be hung up! */
|
||||
res=AST_PBX_KEEPALIVE;
|
||||
break;
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Unable to park call %s\n", chan->name);
|
||||
}
|
||||
/* XXX Maybe we should have another message here instead of invalid extension XXX */
|
||||
} else if (ast_exists_extension(chan, peer->context, newext, 1, peer->callerid)) {
|
||||
/* Set the channel's new extension, since it exists, using peer context */
|
||||
strncpy(chan->exten, newext, sizeof(chan->exten));
|
||||
strncpy(chan->context, peer->context, sizeof(chan->context));
|
||||
chan->priority = 0;
|
||||
ast_frfree(f);
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Transferring %s to '%s' (context %s) priority 1\n", chan->name, chan->exten, chan->context);
|
||||
res=0;
|
||||
break;
|
||||
} else {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Unable to find extension '%s' in context %s\n", newext, peer->context);
|
||||
}
|
||||
res = ast_streamfile(peer, "pbx-invalid", chan->language);
|
||||
if (res)
|
||||
break;
|
||||
res = ast_waitstream(peer, AST_DIGIT_ANY);
|
||||
ast_stopstream(peer);
|
||||
res = 0;
|
||||
} else {
|
||||
#if 1
|
||||
ast_log(LOG_DEBUG, "Read from %s (%d,%d)\n", who->name, f->frametype, f->subclass);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static int park_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
struct ast_channel *peer=NULL;
|
||||
struct parkeduser *pu, *pl=NULL;
|
||||
int park;
|
||||
if (!data) {
|
||||
ast_log(LOG_WARNING, "Park requires an argument (extension number)\n");
|
||||
return -1;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
park = atoi((char *)data);
|
||||
ast_pthread_mutex_lock(&parking_lock);
|
||||
pu = parkinglot;
|
||||
while(pu) {
|
||||
if (pu->parkingnum == park) {
|
||||
if (pl)
|
||||
pl->next = pu->next;
|
||||
else
|
||||
parkinglot = pu->next;
|
||||
break;
|
||||
}
|
||||
pu = pu->next;
|
||||
}
|
||||
ast_pthread_mutex_unlock(&parking_lock);
|
||||
if (pu) {
|
||||
peer = pu->chan;
|
||||
free(pu);
|
||||
}
|
||||
if (peer) {
|
||||
res = ast_channel_make_compatible(chan, peer);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
|
||||
ast_hangup(peer);
|
||||
return -1;
|
||||
}
|
||||
/* This runs sorta backwards, since we give the incoming channel control, as if it
|
||||
were the person called. */
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to parked call %d\n", chan->name, park);
|
||||
res = bridge_call(peer, chan, 1);
|
||||
/* Simulate the PBX hanging up */
|
||||
if (res != AST_PBX_KEEPALIVE)
|
||||
ast_hangup(peer);
|
||||
return -1;
|
||||
} else {
|
||||
/* XXX Play a message XXX */
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Channel %s tried to talk to non-existant parked call %d\n", chan->name, park);
|
||||
res = -1;
|
||||
}
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int dial_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=-1;
|
||||
@@ -599,7 +275,7 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
ast_log(LOG_WARNING, "Out of memory\n");
|
||||
return -1;
|
||||
}
|
||||
strncpy(info, (char *)data, strlen((char *)data) + AST_MAX_EXTENSION);
|
||||
strncpy(info, (char *)data, strlen((char *)data) + AST_MAX_EXTENSION-1);
|
||||
peers = info;
|
||||
if (peers) {
|
||||
timeout = strchr(info, '|');
|
||||
@@ -641,14 +317,19 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
ast_log(LOG_WARNING, "Out of memory\n");
|
||||
goto out;
|
||||
}
|
||||
if (transfer && (strchr(transfer, 't')))
|
||||
tmp->allowredirect = 1;
|
||||
else
|
||||
tmp->allowredirect = 0;
|
||||
strncpy(numsubst, number, sizeof(numsubst));
|
||||
memset(tmp, 0, sizeof(struct localuser));
|
||||
if (transfer) {
|
||||
if (strchr(transfer, 't'))
|
||||
tmp->allowredirect = 1;
|
||||
if (strchr(transfer, 'r'))
|
||||
tmp->ringbackonly = 1;
|
||||
if (strchr(transfer, 'm'))
|
||||
tmp->musiconhold = 1;
|
||||
}
|
||||
strncpy(numsubst, number, sizeof(numsubst)-1);
|
||||
/* If we're dialing by extension, look at the extension to know what to dial */
|
||||
if ((newnum = strstr(numsubst, "BYEXTENSION"))) {
|
||||
strncpy(restofit, newnum + strlen("BYEXTENSION"), sizeof(restofit));
|
||||
strncpy(restofit, newnum + strlen("BYEXTENSION"), sizeof(restofit)-1);
|
||||
snprintf(newnum, sizeof(numsubst) - (newnum - numsubst), "%s%s", chan->exten,restofit);
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst);
|
||||
@@ -657,19 +338,43 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
tmp->chan = ast_request(tech, chan->nativeformats, numsubst);
|
||||
if (!tmp->chan) {
|
||||
/* If we can't, just go on to the next call */
|
||||
ast_log(LOG_WARNING, "Unable to create channel of type '%s'\n", tech);
|
||||
ast_log(LOG_NOTICE, "Unable to create channel of type '%s'\n", tech);
|
||||
if (chan->cdr)
|
||||
ast_cdr_busy(chan->cdr);
|
||||
free(tmp);
|
||||
cur = rest;
|
||||
continue;
|
||||
}
|
||||
if (strlen(tmp->chan->call_forward)) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Forwarding call to '%s@%s'\n", tmp->chan->call_forward, tmp->chan->context);
|
||||
/* Setup parameters */
|
||||
strncpy(chan->exten, tmp->chan->call_forward, sizeof(chan->exten));
|
||||
strncpy(chan->context, tmp->chan->context, sizeof(chan->context));
|
||||
chan->priority = 0;
|
||||
to = 0;
|
||||
ast_hangup(tmp->chan);
|
||||
free(tmp);
|
||||
cur = rest;
|
||||
break;
|
||||
}
|
||||
tmp->chan->appl = "AppDial";
|
||||
tmp->chan->data = "(Outgoing Line)";
|
||||
tmp->chan->whentohangup = 0;
|
||||
if (tmp->chan->callerid)
|
||||
free(tmp->chan->callerid);
|
||||
if (tmp->chan->ani)
|
||||
free(tmp->chan->ani);
|
||||
if (chan->callerid)
|
||||
tmp->chan->callerid = strdup(chan->callerid);
|
||||
else
|
||||
tmp->chan->callerid = NULL;
|
||||
if (chan->ani)
|
||||
tmp->chan->ani = strdup(chan->ani);
|
||||
else
|
||||
tmp->chan->ani = NULL;
|
||||
/* Presense of ADSI CPE on outgoing channel follows ours */
|
||||
tmp->chan->adsicpe = chan->adsicpe;
|
||||
/* Place the call, but don't wait on the answer */
|
||||
res = ast_call(tmp->chan, numsubst, 0);
|
||||
if (res) {
|
||||
@@ -715,6 +420,9 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
conversation. */
|
||||
hanguptree(outgoing, peer);
|
||||
outgoing = NULL;
|
||||
/* If appropriate, log that we have a destination channel */
|
||||
if (chan->cdr)
|
||||
ast_cdr_setdestchan(chan->cdr, peer->name);
|
||||
/* Make sure channels are compatible */
|
||||
res = ast_channel_make_compatible(chan, peer);
|
||||
if (res < 0) {
|
||||
@@ -730,7 +438,7 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
int x = 2;
|
||||
ast_channel_setoption(peer,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
|
||||
}
|
||||
res = bridge_call(chan, peer, allowredir);
|
||||
res = ast_bridge_call(chan, peer, allowredir);
|
||||
ast_hangup(peer);
|
||||
}
|
||||
out:
|
||||
@@ -749,25 +457,7 @@ int unload_module(void)
|
||||
int load_module(void)
|
||||
{
|
||||
int res;
|
||||
int x;
|
||||
struct ast_context *con;
|
||||
char exten[AST_MAX_EXTENSION];
|
||||
con = ast_context_find(parking_con);
|
||||
if (!con) {
|
||||
con = ast_context_create(parking_con, registrar);
|
||||
if (!con) {
|
||||
ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
for(x=parking_start; x<=parking_stop;x++) {
|
||||
snprintf(exten, sizeof(exten), "%d", x);
|
||||
ast_add_extension2(con, 1, exten, 1, NULL, parkedcall, strdup(exten), free, registrar);
|
||||
}
|
||||
pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
|
||||
res = ast_register_application(parkedcall, park_exec, synopsis, descrip);
|
||||
if (!res)
|
||||
res = ast_register_application(app, dial_exec, synopsis, descrip);
|
||||
res = ast_register_application(app, dial_exec, synopsis, descrip);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
@@ -131,7 +132,8 @@ static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char *
|
||||
memset(ext, 0, sizeof(ext));
|
||||
ext[0] = digit;
|
||||
res = 0;
|
||||
if (ast_readstring(chan, ext + 1, NUMDIGITS, 3000, 3000, "#") < 0) res = -1;
|
||||
if (ast_readstring(chan, ext + 1, NUMDIGITS - 1, 3000, 3000, "#") < 0) res = -1;
|
||||
printf("Res: %d, ext: %s\n", res, ext);
|
||||
if (!res) {
|
||||
/* Search for all names which start with those digits */
|
||||
v = ast_variable_browse(cfg, context);
|
||||
@@ -166,13 +168,13 @@ static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char *
|
||||
if (v) {
|
||||
/* We have a match -- play a greeting if they have it */
|
||||
snprintf(fn, sizeof(fn), "%s/vm/%s/greet", AST_SPOOL_DIR, v->name);
|
||||
if (ast_fileexists(fn, NULL, chan->language)) {
|
||||
if (ast_fileexists(fn, NULL, chan->language) > 0) {
|
||||
res = ast_streamfile(chan, fn, chan->language);
|
||||
if (!res)
|
||||
res = ast_waitstream(chan, AST_DIGIT_ANY);
|
||||
ast_stopstream(chan);
|
||||
} else {
|
||||
res = ast_say_digit_str(chan, v->name, chan->language);
|
||||
res = ast_say_digit_str(chan, v->name, AST_DIGIT_ANY, chan->language);
|
||||
}
|
||||
ahem:
|
||||
if (!res)
|
||||
@@ -184,9 +186,9 @@ ahem:
|
||||
ast_stopstream(chan);
|
||||
if (res > -1) {
|
||||
if (res == '1') {
|
||||
strncpy(chan->exten, v->name, sizeof(chan->exten));
|
||||
strncpy(chan->exten, v->name, sizeof(chan->exten)-1);
|
||||
chan->priority = 0;
|
||||
strncpy(chan->context, context, sizeof(chan->context));
|
||||
strncpy(chan->context, context, sizeof(chan->context)-1);
|
||||
res = 0;
|
||||
break;
|
||||
} else if (res == '*') {
|
||||
|
||||
188
apps/app_disa.c
188
apps/app_disa.c
@@ -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>
|
||||
@@ -25,7 +26,9 @@
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#define TONE_BLOCK_SIZE 200
|
||||
/*
|
||||
#define TONE_BLOCK_SIZE 320
|
||||
*/
|
||||
|
||||
static char *tdesc = "DISA (Direct Inward System Access) Application";
|
||||
|
||||
@@ -72,23 +75,21 @@ STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static float loudness=8192.0;
|
||||
static float loudness=4096.0;
|
||||
|
||||
int firstdigittimeout = 10000; /* 10 seconds first digit timeout */
|
||||
int digittimeout = 5000; /* 5 seconds subsequent digit timeout */
|
||||
int firstdigittimeout = 20000; /* 20 seconds first digit timeout */
|
||||
int digittimeout = 10000; /* 10 seconds subsequent digit timeout */
|
||||
|
||||
static void make_tone_block(unsigned char *data, float f1, float f2, int *x);
|
||||
|
||||
static void make_tone_block(unsigned char *data, float f1, float f2, int *x)
|
||||
static void make_tone_block(unsigned char *data, float f1, float f2, int len, int *x)
|
||||
{
|
||||
int i;
|
||||
float val;
|
||||
|
||||
for(i = 0; i < TONE_BLOCK_SIZE; i++)
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
val = loudness * sin((f1 * 2.0 * M_PI * (*x))/8000.0);
|
||||
val += loudness * sin((f2 * 2.0 * M_PI * (*x)++)/8000.0);
|
||||
data[i] = ast_lin2mu[(int)val + 32768];
|
||||
data[i] = AST_LIN2MU((int)val);
|
||||
}
|
||||
/* wrap back around from 8000 */
|
||||
if (*x >= 8000) *x = 0;
|
||||
@@ -108,13 +109,12 @@ static int disa_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int i,j,k,x;
|
||||
struct localuser *u;
|
||||
char tmp[256],exten[AST_MAX_EXTENSION];
|
||||
unsigned char tone_block[TONE_BLOCK_SIZE],sil_block[TONE_BLOCK_SIZE];
|
||||
char tmp[256],exten[AST_MAX_EXTENSION],acctcode[20];
|
||||
unsigned char tone_block[640],sil_block[640];
|
||||
char *ourcontext;
|
||||
struct ast_frame *f,wf;
|
||||
fd_set readfds;
|
||||
int waitfor_notime;
|
||||
struct timeval notime = { 0,0 }, lastout, now, lastdigittime;
|
||||
struct timeval lastout, now, lastdigittime;
|
||||
int res;
|
||||
FILE *fp;
|
||||
|
||||
if (ast_set_write_format(chan,AST_FORMAT_ULAW))
|
||||
@@ -129,12 +129,12 @@ static int disa_exec(struct ast_channel *chan, void *data)
|
||||
}
|
||||
lastout.tv_sec = lastout.tv_usec = 0;
|
||||
/* make block of silence */
|
||||
memset(sil_block,0x7f,TONE_BLOCK_SIZE);
|
||||
memset(sil_block,0x7f,sizeof(sil_block));
|
||||
if (!data || !strlen((char *)data)) {
|
||||
ast_log(LOG_WARNING, "disa requires an argument (passcode/passcode file)\n");
|
||||
return -1;
|
||||
}
|
||||
strncpy(tmp, (char *)data, sizeof(tmp));
|
||||
strncpy(tmp, (char *)data, sizeof(tmp)-1);
|
||||
strtok(tmp, "|");
|
||||
ourcontext = strtok(NULL, "|");
|
||||
/* if context not specified, use "disa" */
|
||||
@@ -165,33 +165,11 @@ static int disa_exec(struct ast_channel *chan, void *data)
|
||||
((k) ? "extension" : "password"),chan->name);
|
||||
goto reorder;
|
||||
}
|
||||
/* if first digit or ignore, send dialtone */
|
||||
if ((!i) || (ast_ignore_pattern(ourcontext,exten) && k))
|
||||
{
|
||||
gettimeofday(&now,NULL);
|
||||
if (lastout.tv_sec &&
|
||||
(ms_diff(&now,&lastout) < 25)) continue;
|
||||
lastout.tv_sec = now.tv_sec;
|
||||
lastout.tv_usec = now.tv_usec;
|
||||
wf.frametype = AST_FRAME_VOICE;
|
||||
wf.subclass = AST_FORMAT_ULAW;
|
||||
wf.offset = AST_FRIENDLY_OFFSET;
|
||||
wf.mallocd = 0;
|
||||
wf.data = tone_block;
|
||||
wf.datalen = TONE_BLOCK_SIZE;
|
||||
/* make this tone block */
|
||||
make_tone_block(tone_block,350.0,440.0,&x);
|
||||
wf.timelen = wf.datalen / 8;
|
||||
if (ast_write(chan, &wf))
|
||||
{
|
||||
ast_log(LOG_WARNING, "DISA Failed to write frame on %s\n",chan->name);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
if ((res = ast_waitfor(chan, -1) < 0)) {
|
||||
ast_log(LOG_DEBUG, "Waitfor returned %d\n", res);
|
||||
continue;
|
||||
}
|
||||
waitfor_notime = notime.tv_usec + notime.tv_sec * 1000;
|
||||
if (!ast_waitfor_nandfds(&chan, 1, &(chan->fds[0]), 1, NULL, NULL,
|
||||
&waitfor_notime)) continue;
|
||||
|
||||
f = ast_read(chan);
|
||||
if (f == NULL)
|
||||
{
|
||||
@@ -204,6 +182,27 @@ static int disa_exec(struct ast_channel *chan, void *data)
|
||||
ast_frfree(f);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
if (!i || (ast_ignore_pattern(ourcontext, exten) && k)) {
|
||||
wf.frametype = AST_FRAME_VOICE;
|
||||
wf.subclass = AST_FORMAT_ULAW;
|
||||
wf.offset = AST_FRIENDLY_OFFSET;
|
||||
wf.mallocd = 0;
|
||||
wf.data = tone_block;
|
||||
wf.datalen = f->datalen;
|
||||
make_tone_block(tone_block, 350, 440, f->datalen, &x);
|
||||
wf.timelen = wf.datalen / 8;
|
||||
ast_frfree(f);
|
||||
if (ast_write(chan, &wf))
|
||||
{
|
||||
ast_log(LOG_WARNING, "DISA Failed to write frame on %s\n",chan->name);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
} else
|
||||
ast_frfree(f);
|
||||
continue;
|
||||
}
|
||||
/* if not DTMF, just do it again */
|
||||
if (f->frametype != AST_FRAME_DTMF)
|
||||
@@ -211,8 +210,10 @@ static int disa_exec(struct ast_channel *chan, void *data)
|
||||
ast_frfree(f);
|
||||
continue;
|
||||
}
|
||||
|
||||
j = f->subclass; /* save digit */
|
||||
ast_frfree(f);
|
||||
|
||||
gettimeofday(&lastdigittime,NULL);
|
||||
/* got a DTMF tone */
|
||||
if (i < AST_MAX_EXTENSION) /* if still valid number of digits */
|
||||
@@ -255,10 +256,14 @@ static int disa_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
ast_log(LOG_WARNING,"DISA on chan %s got bad password %s\n",chan->name,exten);
|
||||
goto reorder;
|
||||
|
||||
}
|
||||
/* password good, set to dial state */
|
||||
ast_log(LOG_WARNING,"DISA on chan %s password is good\n",chan->name);
|
||||
k = 1;
|
||||
i = 0; /* re-set buffer pointer */
|
||||
exten[sizeof(acctcode)] = 0;
|
||||
strcpy(acctcode,exten);
|
||||
exten[0] = 0;
|
||||
ast_log(LOG_DEBUG,"Successful DISA log-in on chan %s\n",chan->name);
|
||||
continue;
|
||||
@@ -272,7 +277,9 @@ static int disa_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
strcpy(chan->exten,exten);
|
||||
strcpy(chan->context,ourcontext);
|
||||
strcpy(chan->accountcode,acctcode);
|
||||
chan->priority = 0;
|
||||
ast_cdr_init(chan->cdr,chan);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
@@ -280,95 +287,46 @@ static int disa_exec(struct ast_channel *chan, void *data)
|
||||
if (ast_canmatch_extension(chan,ourcontext,exten,1, chan->callerid)) continue;
|
||||
}
|
||||
reorder:
|
||||
|
||||
/* something is invalid, give em reorder forever */
|
||||
x = 0;
|
||||
k = 0; /* k = 0 means busy tone, k = 1 means silence) */
|
||||
i = 0; /* Number of samples we've done */
|
||||
for(;;)
|
||||
{
|
||||
for(i = 0; i < 10; i++)
|
||||
{
|
||||
do gettimeofday(&now,NULL);
|
||||
while (lastout.tv_sec &&
|
||||
(ms_diff(&now,&lastout) < 25)) ;
|
||||
lastout.tv_sec = now.tv_sec;
|
||||
lastout.tv_usec = now.tv_usec;
|
||||
if (ast_waitfor(chan, -1) < 0)
|
||||
break;
|
||||
f = ast_read(chan);
|
||||
if (!f)
|
||||
break;
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
wf.frametype = AST_FRAME_VOICE;
|
||||
wf.subclass = AST_FORMAT_ULAW;
|
||||
wf.offset = AST_FRIENDLY_OFFSET;
|
||||
wf.mallocd = 0;
|
||||
wf.data = tone_block;
|
||||
wf.datalen = TONE_BLOCK_SIZE;
|
||||
/* make this tone block */
|
||||
make_tone_block(tone_block,480.0,620.0,&x);
|
||||
wf.datalen = f->datalen;
|
||||
wf.timelen = wf.datalen / 8;
|
||||
if (ast_write(chan, &wf))
|
||||
if (k)
|
||||
memset(tone_block, 0x7f, wf.datalen);
|
||||
else
|
||||
make_tone_block(tone_block,480.0, 620.0,wf.datalen, &x);
|
||||
i += wf.datalen / 8;
|
||||
if (i > 250) {
|
||||
i = 0;
|
||||
k = !k;
|
||||
}
|
||||
if (ast_write(chan, &wf))
|
||||
{
|
||||
ast_log(LOG_WARNING, "DISA Failed to write frame on %s\n",chan->name);
|
||||
ast_log(LOG_WARNING, "DISA Failed to write frame on %s\n",chan->name);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(chan->fds[0],&readfds);
|
||||
/* if no read avail, do send again */
|
||||
if (select(chan->fds[0] + 1,&readfds,NULL,
|
||||
NULL,¬ime) < 1) continue;
|
||||
/* read frame */
|
||||
f = ast_read(chan);
|
||||
if (f == NULL)
|
||||
{
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
if ((f->frametype == AST_FRAME_CONTROL) &&
|
||||
(f->subclass == AST_CONTROL_HANGUP))
|
||||
{
|
||||
ast_frfree(f);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
for(i = 0; i < 10; i++)
|
||||
{
|
||||
do gettimeofday(&now,NULL);
|
||||
while (lastout.tv_sec &&
|
||||
(ms_diff(&now,&lastout) < 25)) ;
|
||||
lastout.tv_sec = now.tv_sec;
|
||||
lastout.tv_usec = now.tv_usec;
|
||||
wf.frametype = AST_FRAME_VOICE;
|
||||
wf.subclass = AST_FORMAT_ULAW;
|
||||
wf.offset = AST_FRIENDLY_OFFSET;
|
||||
wf.mallocd = 0;
|
||||
wf.data = sil_block;
|
||||
wf.datalen = TONE_BLOCK_SIZE;
|
||||
wf.timelen = wf.datalen / 8;
|
||||
if (ast_write(chan, &wf))
|
||||
{
|
||||
ast_log(LOG_WARNING, "DISA Failed to write frame on %s\n",chan->name);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(chan->fds[0],&readfds);
|
||||
/* if no read avail, do send again */
|
||||
if (select(chan->fds[0] + 1,&readfds,NULL,
|
||||
NULL,¬ime) < 1) continue;
|
||||
/* read frame */
|
||||
f = ast_read(chan);
|
||||
if (f == NULL)
|
||||
{
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
if ((f->frametype == AST_FRAME_CONTROL) &&
|
||||
(f->subclass == AST_CONTROL_HANGUP))
|
||||
{
|
||||
ast_frfree(f);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
@@ -44,8 +45,13 @@ static int echo_exec(struct ast_channel *chan, void *data)
|
||||
struct localuser *u;
|
||||
struct ast_frame *f;
|
||||
LOCAL_USER_ADD(u);
|
||||
ast_set_write_format(chan, ast_best_codec(chan->nativeformats));
|
||||
ast_set_read_format(chan, ast_best_codec(chan->nativeformats));
|
||||
/* Do our thing here */
|
||||
while((f = ast_read(chan))) {
|
||||
while(ast_waitfor(chan, -1) > -1) {
|
||||
f = ast_read(chan);
|
||||
if (!f)
|
||||
break;
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
if (ast_write(chan, f))
|
||||
break;
|
||||
|
||||
149
apps/app_getcpeid.c
Normal file
149
apps/app_getcpeid.c
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Execute arbitrary system commands
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/adsi.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
static char *tdesc = "Get ADSI CPE ID";
|
||||
|
||||
static char *app = "GetCPEID";
|
||||
|
||||
static char *synopsis = "Get ADSI CPE ID";
|
||||
|
||||
static char *descrip =
|
||||
" GetCPEID: Obtains and displays CPE ID and other information in order to\n"
|
||||
"properly setup zapata.conf for on-hook operations. Returns -1 on hanup\n"
|
||||
"only.";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int cpeid_setstatus(struct ast_channel *chan, char *stuff[], int voice)
|
||||
{
|
||||
int justify[5] = { ADSI_JUST_CENT, ADSI_JUST_LEFT, ADSI_JUST_LEFT, ADSI_JUST_LEFT };
|
||||
char *tmp[5];
|
||||
int x;
|
||||
for (x=0;x<4;x++)
|
||||
tmp[x] = stuff[x];
|
||||
tmp[4] = NULL;
|
||||
return adsi_print(chan, tmp, justify, voice);
|
||||
}
|
||||
|
||||
static int cpeid_exec(struct ast_channel *chan, void *idata)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
unsigned char cpeid[4];
|
||||
int gotgeometry = 0;
|
||||
int gotcpeid = 0;
|
||||
int width, height, buttons;
|
||||
char data[4][80];
|
||||
char *stuff[4];
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
stuff[0] = data[0];
|
||||
stuff[1] = data[1];
|
||||
stuff[2] = data[2];
|
||||
stuff[3] = data[3];
|
||||
memset(data, 0, sizeof(data));
|
||||
strcpy(stuff[0], "** CPE Info **");
|
||||
strcpy(stuff[1], "Identifying CPE...");
|
||||
strcpy(stuff[2], "Please wait...");
|
||||
res = adsi_load_session(chan, NULL, 0, 1);
|
||||
if (res > 0) {
|
||||
cpeid_setstatus(chan, stuff, 0);
|
||||
res = adsi_get_cpeid(chan, cpeid, 0);
|
||||
if (res > 0) {
|
||||
gotcpeid = 1;
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Got CPEID of '%02x:%02x:%02x:%02x' on '%s'\n", cpeid[0], cpeid[1], cpeid[2], cpeid[3], chan->name);
|
||||
}
|
||||
if (res > -1) {
|
||||
strcpy(stuff[1], "Measuring CPE...");
|
||||
strcpy(stuff[2], "Please wait...");
|
||||
cpeid_setstatus(chan, stuff, 0);
|
||||
res = adsi_get_cpeinfo(chan, &width, &height, &buttons, 0);
|
||||
if (res > -1) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "CPE has %d lines, %d columns, and %d buttons on '%s'\n", height, width, buttons, chan->name);
|
||||
gotgeometry = 1;
|
||||
}
|
||||
}
|
||||
if (res > -1) {
|
||||
if (gotcpeid)
|
||||
sprintf(stuff[1], "CPEID: %02x:%02x:%02x:%02x", cpeid[0], cpeid[1], cpeid[2], cpeid[3]);
|
||||
else
|
||||
strcpy(stuff[1], "CPEID Unknown");
|
||||
if (gotgeometry)
|
||||
sprintf(stuff[2], "Geom: %dx%d, %d buttons", width, height, buttons);
|
||||
else
|
||||
strcpy(stuff[2], "Geometry unknown");
|
||||
strcpy(stuff[3], "Press # to exit");
|
||||
cpeid_setstatus(chan, stuff, 1);
|
||||
for(;;) {
|
||||
res = ast_waitfordigit(chan, 1000);
|
||||
if (res < 0)
|
||||
break;
|
||||
if (res == '#') {
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
adsi_unload_session(chan);
|
||||
}
|
||||
}
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, cpeid_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/frame.h>
|
||||
#include <asterisk/logger.h>
|
||||
@@ -47,7 +48,7 @@ STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static pthread_mutex_t sound_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t sound_lock = AST_MUTEX_INITIALIZER;
|
||||
static int sound = -1;
|
||||
|
||||
static int write_audio(short *data, int len)
|
||||
|
||||
501
apps/app_meetme.c
Normal file
501
apps/app_meetme.c
Normal file
@@ -0,0 +1,501 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Meet me conference bridge
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/config.h>
|
||||
#include <asterisk/app.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/cli.h>
|
||||
#include <asterisk/say.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <pthread.h>
|
||||
#include <linux/zaptel.h>
|
||||
|
||||
static char *tdesc = "Simple MeetMe conference bridge";
|
||||
|
||||
static char *app = "MeetMe";
|
||||
static char *app2 = "MeetMeCount";
|
||||
|
||||
static char *synopsis = "Simple MeetMe conference bridge";
|
||||
static char *synopsis2 = "MeetMe participant count";
|
||||
|
||||
static char *descrip =
|
||||
" MeetMe(confno): Enters the user into a specified MeetMe conference.\n"
|
||||
"If the conference number is omitted, the user will be prompted to enter\n"
|
||||
"one. This application always returns -1. A ZAPTEL INTERFACE MUST BE\n"
|
||||
"INSTALLED FOR CONFERENCING FUNCTIONALITY.\n";
|
||||
|
||||
static char *descrip2 =
|
||||
" MeetMe2(confno): Plays back the number of users in the specified MeetMe\n"
|
||||
"conference. Returns 0 on success or -1 on a hangup. A ZAPTEL INTERFACE\n"
|
||||
"MUST BE INSTALLED FOR CONFERENCING FUNCTIONALITY.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static struct conf {
|
||||
char confno[80]; /* Conference */
|
||||
int fd; /* Announcements fd */
|
||||
int zapconf; /* Zaptel Conf # */
|
||||
int users; /* Number of active users */
|
||||
time_t start; /* Start time (s) */
|
||||
struct conf *next;
|
||||
} *confs;
|
||||
|
||||
static pthread_mutex_t conflock = AST_MUTEX_INITIALIZER;
|
||||
|
||||
#include "enter.h"
|
||||
#include "leave.h"
|
||||
|
||||
#define ENTER 0
|
||||
#define LEAVE 1
|
||||
|
||||
#define CONF_SIZE 160
|
||||
|
||||
static int careful_write(int fd, unsigned char *data, int len)
|
||||
{
|
||||
int res;
|
||||
while(len) {
|
||||
res = write(fd, data, len);
|
||||
if (res < 1) {
|
||||
if (errno != EAGAIN) {
|
||||
ast_log(LOG_WARNING, "Failed to write audio data to conference: %s\n", strerror(errno));
|
||||
return -1;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
len -= res;
|
||||
data += res;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void conf_play(struct conf *conf, int sound)
|
||||
{
|
||||
unsigned char *data;
|
||||
int len;
|
||||
ast_pthread_mutex_lock(&conflock);
|
||||
switch(sound) {
|
||||
case ENTER:
|
||||
data = enter;
|
||||
len = sizeof(enter);
|
||||
break;
|
||||
case LEAVE:
|
||||
data = leave;
|
||||
len = sizeof(leave);
|
||||
break;
|
||||
default:
|
||||
data = NULL;
|
||||
len = 0;
|
||||
}
|
||||
if (data)
|
||||
careful_write(conf->fd, data, len);
|
||||
pthread_mutex_unlock(&conflock);
|
||||
}
|
||||
|
||||
static struct conf *build_conf(char *confno, int make)
|
||||
{
|
||||
struct conf *cnf;
|
||||
struct zt_confinfo ztc;
|
||||
ast_pthread_mutex_lock(&conflock);
|
||||
cnf = confs;
|
||||
while(cnf) {
|
||||
if (!strcmp(confno, cnf->confno))
|
||||
break;
|
||||
cnf = cnf->next;
|
||||
}
|
||||
if (!cnf && make) {
|
||||
cnf = malloc(sizeof(struct conf));
|
||||
if (cnf) {
|
||||
/* Make a new one */
|
||||
memset(cnf, 0, sizeof(struct conf));
|
||||
strncpy(cnf->confno, confno, sizeof(cnf->confno) - 1);
|
||||
cnf->fd = open("/dev/zap/pseudo", O_RDWR);
|
||||
if (cnf->fd < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to open pseudo channel\n");
|
||||
free(cnf);
|
||||
cnf = NULL;
|
||||
goto cnfout;
|
||||
}
|
||||
memset(&ztc, 0, sizeof(ztc));
|
||||
/* Setup a new zap conference */
|
||||
ztc.chan = 0;
|
||||
ztc.confno = -1;
|
||||
ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER;
|
||||
if (ioctl(cnf->fd, ZT_SETCONF, &ztc)) {
|
||||
ast_log(LOG_WARNING, "Error setting conference\n");
|
||||
close(cnf->fd);
|
||||
free(cnf);
|
||||
cnf = NULL;
|
||||
goto cnfout;
|
||||
}
|
||||
cnf->start = time(NULL);
|
||||
cnf->zapconf = ztc.confno;
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Crated ZapTel conference %d for conference '%s'\n", cnf->zapconf, cnf->confno);
|
||||
cnf->next = confs;
|
||||
confs = cnf;
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Out of memory\n");
|
||||
}
|
||||
cnfout:
|
||||
if (cnf && make)
|
||||
cnf->users++;
|
||||
ast_pthread_mutex_unlock(&conflock);
|
||||
return cnf;
|
||||
}
|
||||
|
||||
static int confs_show(int fd, int argc, char **argv)
|
||||
{
|
||||
struct conf *conf;
|
||||
int hr, min, sec;
|
||||
time_t now;
|
||||
|
||||
now = time(NULL);
|
||||
if (argc != 2)
|
||||
return RESULT_SHOWUSAGE;
|
||||
conf = confs;
|
||||
if (!conf) {
|
||||
ast_cli(fd, "No active conferences.\n");
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
ast_cli(fd, "Conf Num Parties Activity\n");
|
||||
while(conf) {
|
||||
hr = (now - conf->start) / 3600;
|
||||
min = ((now - conf->start) % 3600) / 60;
|
||||
sec = (now - conf->start) % 60;
|
||||
|
||||
ast_cli(fd, "%-12.12s %4.4d %02d:%02d:%02d\n",
|
||||
conf->confno, conf->users, hr, min, sec);
|
||||
conf = conf->next;
|
||||
}
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static char show_confs_usage[] =
|
||||
"Usage: show conferences\n"
|
||||
" Provides summary information on conferences with active\n"
|
||||
" participation.\n";
|
||||
|
||||
static struct ast_cli_entry cli_show_confs = {
|
||||
{ "show", "conferences", NULL }, confs_show,
|
||||
"Show status of conferences", show_confs_usage, NULL };
|
||||
|
||||
static void conf_run(struct ast_channel *chan, struct conf *conf)
|
||||
{
|
||||
struct conf *prev=NULL, *cur;
|
||||
int fd;
|
||||
struct zt_confinfo ztc;
|
||||
struct ast_frame *f;
|
||||
struct ast_channel *c;
|
||||
struct ast_frame fr;
|
||||
int outfd;
|
||||
int ms;
|
||||
int nfds;
|
||||
int res;
|
||||
int flags;
|
||||
int retryzap=0;
|
||||
|
||||
ZT_BUFFERINFO bi;
|
||||
char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET];
|
||||
char *buf = __buf + AST_FRIENDLY_OFFSET;
|
||||
|
||||
/* Set it into U-law mode (write) */
|
||||
if (ast_set_write_format(chan, AST_FORMAT_ULAW) < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to set '%s' to write ulaw mode\n", chan->name);
|
||||
goto outrun;
|
||||
}
|
||||
|
||||
/* Set it into U-law mode (read) */
|
||||
if (ast_set_read_format(chan, AST_FORMAT_ULAW) < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to set '%s' to read ulaw mode\n", chan->name);
|
||||
goto outrun;
|
||||
}
|
||||
zapretry:
|
||||
|
||||
if (retryzap || strcasecmp(chan->type, "Zap")) {
|
||||
fd = open("/dev/zap/pseudo", O_RDWR);
|
||||
if (fd < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
|
||||
goto outrun;
|
||||
}
|
||||
/* Make non-blocking */
|
||||
flags = fcntl(fd, F_GETFL);
|
||||
if (flags < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to get flags: %s\n", strerror(errno));
|
||||
close(fd);
|
||||
goto outrun;
|
||||
}
|
||||
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) {
|
||||
ast_log(LOG_WARNING, "Unable to set flags: %s\n", strerror(errno));
|
||||
close(fd);
|
||||
goto outrun;
|
||||
}
|
||||
/* Setup buffering information */
|
||||
memset(&bi, 0, sizeof(bi));
|
||||
bi.bufsize = CONF_SIZE;
|
||||
bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
|
||||
bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
|
||||
bi.numbufs = 4;
|
||||
if (ioctl(fd, ZT_SET_BUFINFO, &bi)) {
|
||||
ast_log(LOG_WARNING, "Unable to set buffering information: %s\n", strerror(errno));
|
||||
close(fd);
|
||||
goto outrun;
|
||||
}
|
||||
nfds = 1;
|
||||
} else {
|
||||
/* XXX Make sure we're not running on a pseudo channel XXX */
|
||||
fd = chan->fds[0];
|
||||
nfds = 0;
|
||||
}
|
||||
memset(&ztc, 0, sizeof(ztc));
|
||||
/* Check to see if we're in a conference... */
|
||||
ztc.chan = 0;
|
||||
if (ioctl(fd, ZT_GETCONF, &ztc)) {
|
||||
ast_log(LOG_WARNING, "Error getting conference\n");
|
||||
close(fd);
|
||||
goto outrun;
|
||||
}
|
||||
if (ztc.confmode) {
|
||||
/* Whoa, already in a conference... Retry... */
|
||||
if (!retryzap) {
|
||||
ast_log(LOG_DEBUG, "Zap channel is in a conference already, retrying with pseudo\n");
|
||||
retryzap = 1;
|
||||
goto zapretry;
|
||||
}
|
||||
}
|
||||
memset(&ztc, 0, sizeof(ztc));
|
||||
/* Add us to the conference */
|
||||
ztc.chan = 0;
|
||||
ztc.confno = conf->zapconf;
|
||||
ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER;
|
||||
if (ioctl(fd, ZT_SETCONF, &ztc)) {
|
||||
ast_log(LOG_WARNING, "Error setting conference\n");
|
||||
close(fd);
|
||||
goto outrun;
|
||||
}
|
||||
ast_log(LOG_DEBUG, "Placed channel %s in ZAP conf %d\n", chan->name, conf->zapconf);
|
||||
/* Run the conference enter tone... */
|
||||
conf_play(conf, ENTER);
|
||||
|
||||
for(;;) {
|
||||
outfd = -1;
|
||||
ms = -1;
|
||||
c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms);
|
||||
if (c) {
|
||||
f = ast_read(c);
|
||||
if (!f)
|
||||
break;
|
||||
if (fd != chan->fds[0]) {
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
if (f->subclass == AST_FORMAT_ULAW) {
|
||||
/* Carefully write */
|
||||
careful_write(fd, f->data, f->datalen);
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Huh? Got a non-ulaw (%d) frame in the conference\n", f->subclass);
|
||||
}
|
||||
}
|
||||
ast_frfree(f);
|
||||
} else if (outfd > -1) {
|
||||
res = read(outfd, buf, CONF_SIZE);
|
||||
if (res > 0) {
|
||||
memset(&fr, 0, sizeof(fr));
|
||||
fr.frametype = AST_FRAME_VOICE;
|
||||
fr.subclass = AST_FORMAT_ULAW;
|
||||
fr.datalen = res;
|
||||
fr.timelen = res / 8;
|
||||
fr.data = buf;
|
||||
fr.offset = AST_FRIENDLY_OFFSET;
|
||||
if (ast_write(chan, &fr) < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to write frame to channel: %s\n", strerror(errno));
|
||||
/* break; */
|
||||
}
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Failed to read frame: %s\n", strerror(errno));
|
||||
}
|
||||
}
|
||||
if (fd != chan->fds[0])
|
||||
close(fd);
|
||||
|
||||
conf_play(conf, LEAVE);
|
||||
|
||||
outrun:
|
||||
|
||||
ast_pthread_mutex_lock(&conflock);
|
||||
/* Clean up */
|
||||
conf->users--;
|
||||
if (!conf->users) {
|
||||
/* No more users -- close this one out */
|
||||
cur = confs;
|
||||
while(cur) {
|
||||
if (cur == conf) {
|
||||
if (prev)
|
||||
prev->next = conf->next;
|
||||
else
|
||||
confs = conf->next;
|
||||
break;
|
||||
}
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
if (!cur)
|
||||
ast_log(LOG_WARNING, "Conference not found\n");
|
||||
close(conf->fd);
|
||||
free(conf);
|
||||
}
|
||||
pthread_mutex_unlock(&conflock);
|
||||
}
|
||||
|
||||
static struct conf *find_conf(char *confno, int make)
|
||||
{
|
||||
struct ast_config *cfg;
|
||||
struct ast_variable *var;
|
||||
struct conf *cnf = NULL;
|
||||
cfg = ast_load("meetme.conf");
|
||||
if (!cfg) {
|
||||
ast_log(LOG_WARNING, "No meetme.conf file :(\n");
|
||||
return NULL;
|
||||
}
|
||||
var = ast_variable_browse(cfg, "rooms");
|
||||
while(var) {
|
||||
if (!strcasecmp(var->name, "conf") &&
|
||||
!strcasecmp(var->value, confno)) {
|
||||
/* Bingo it's a valid conference */
|
||||
cnf = build_conf(confno, make);
|
||||
break;
|
||||
}
|
||||
var = var->next;
|
||||
}
|
||||
if (!var) {
|
||||
ast_log(LOG_DEBUG, "%s isn't a valid conference\n", confno);
|
||||
}
|
||||
ast_destroy(cfg);
|
||||
return cnf;
|
||||
}
|
||||
|
||||
static int count_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
struct localuser *u;
|
||||
int res = 0;
|
||||
struct conf *conf;
|
||||
int cnt;
|
||||
if (!data || !strlen(data)) {
|
||||
ast_log(LOG_WARNING, "MeetMeCount requires an argument (conference number)\n");
|
||||
return -1;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
conf = find_conf(data, 0);
|
||||
if (conf)
|
||||
cnt = conf->users;
|
||||
else
|
||||
cnt = 0;
|
||||
if (chan->state != AST_STATE_UP)
|
||||
ast_answer(chan);
|
||||
res = ast_say_number(chan, cnt, "", chan->language);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int conf_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=-1;
|
||||
struct localuser *u;
|
||||
char confno[80] = "";
|
||||
int allowretry = 0;
|
||||
int retrycnt = 0;
|
||||
struct conf *cnf;
|
||||
|
||||
if (!data || !strlen(data)) {
|
||||
allowretry = 1;
|
||||
data = "";
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
if (chan->state != AST_STATE_UP)
|
||||
ast_answer(chan);
|
||||
retry:
|
||||
/* Parse out the stuff */
|
||||
strncpy(confno, data, sizeof(confno) - 1);
|
||||
|
||||
while(!strlen(confno) && (++retrycnt < 4)) {
|
||||
/* Prompt user for conference number */
|
||||
res = ast_app_getdata(chan, "conf-getconfno",confno, sizeof(confno) - 1, 0);
|
||||
if (res <0) goto out;
|
||||
}
|
||||
if (strlen(confno)) {
|
||||
/* Check the validity of the conference */
|
||||
cnf = find_conf(confno, 1);
|
||||
if (!cnf) {
|
||||
res = ast_streamfile(chan, "conf-invalid", chan->language);
|
||||
if (res < 0)
|
||||
goto out;
|
||||
if (!res)
|
||||
res = ast_waitstream(chan, "");
|
||||
res = -1;
|
||||
if (allowretry) {
|
||||
strcpy(confno, "");
|
||||
goto retry;
|
||||
}
|
||||
} else {
|
||||
/* Run the conference */
|
||||
conf_run(chan, cnf);
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
out:
|
||||
/* Do the conference */
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
ast_cli_unregister(&cli_show_confs);
|
||||
ast_unregister_application(app2);
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
ast_cli_register(&cli_show_confs);
|
||||
ast_register_application(app2, count_exec, synopsis2, descrip2);
|
||||
return ast_register_application(app, conf_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
148
apps/app_milliwatt.c
Normal file
148
apps/app_milliwatt.c
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Digital Milliwatt Test
|
||||
*
|
||||
* Copyright (C) 2002, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Digital Milliwatt (mu-law) Test Application";
|
||||
|
||||
static char *app = "Milliwatt";
|
||||
|
||||
static char *synopsis = "Generate a Constant 1000Hz tone at 0dbm (mu-law)";
|
||||
|
||||
static char *descrip =
|
||||
"Milliwatt(): Generate a Constant 1000Hz tone at 0dbm (mu-law)\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static char digital_milliwatt[] = {0x1e,0x0b,0x0b,0x1e,0x9e,0x8b,0x8b,0x9e} ;
|
||||
|
||||
static void *milliwatt_alloc(struct ast_channel *chan, void *params)
|
||||
{
|
||||
int *indexp;
|
||||
indexp = malloc(sizeof(int));
|
||||
if (indexp == NULL) return(NULL);
|
||||
*indexp = 0;
|
||||
return(indexp);
|
||||
}
|
||||
|
||||
static void milliwatt_release(struct ast_channel *chan, void *data)
|
||||
{
|
||||
free(data);
|
||||
return;
|
||||
}
|
||||
|
||||
static int milliwatt_generate(struct ast_channel *chan, void *data, int len)
|
||||
{
|
||||
struct ast_frame wf;
|
||||
unsigned char waste[AST_FRIENDLY_OFFSET];
|
||||
unsigned char buf[640];
|
||||
int i,*indexp = (int *) data;
|
||||
|
||||
if (len > sizeof(buf))
|
||||
{
|
||||
ast_log(LOG_WARNING,"Only doing %d bytes (%d bytes requested)\n",sizeof(buf),len);
|
||||
len = sizeof(buf);
|
||||
}
|
||||
waste[0] = 0; /* make compiler happy */
|
||||
wf.frametype = AST_FRAME_VOICE;
|
||||
wf.subclass = AST_FORMAT_ULAW;
|
||||
wf.offset = AST_FRIENDLY_OFFSET;
|
||||
wf.mallocd = 0;
|
||||
wf.data = buf;
|
||||
wf.datalen = len;
|
||||
wf.timelen = wf.datalen / 8;
|
||||
wf.src = "app_milliwatt";
|
||||
/* create a buffer containing the digital milliwatt pattern */
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
buf[i] = digital_milliwatt[(*indexp)++];
|
||||
*indexp &= 7;
|
||||
}
|
||||
if (ast_write(chan,&wf) < 0)
|
||||
{
|
||||
ast_log(LOG_WARNING,"Failed to write frame to '%s': %s\n",chan->name,strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ast_generator milliwattgen =
|
||||
{
|
||||
alloc: milliwatt_alloc,
|
||||
release: milliwatt_release,
|
||||
generate: milliwatt_generate,
|
||||
} ;
|
||||
|
||||
static int milliwatt_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
|
||||
struct localuser *u;
|
||||
struct ast_frame *f;
|
||||
LOCAL_USER_ADD(u);
|
||||
ast_set_write_format(chan, AST_FORMAT_ULAW);
|
||||
ast_set_read_format(chan, AST_FORMAT_ULAW);
|
||||
if (chan->state != AST_STATE_UP)
|
||||
{
|
||||
ast_answer(chan);
|
||||
}
|
||||
if (ast_activate_generator(chan,&milliwattgen,"milliwatt") < 0)
|
||||
{
|
||||
ast_log(LOG_WARNING,"Failed to activate generator on '%s'\n",chan->name);
|
||||
return -1;
|
||||
}
|
||||
while(!ast_safe_sleep(chan, 10000));
|
||||
ast_deactivate_generator(chan);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, milliwatt_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
@@ -32,9 +33,11 @@ static char *descrip =
|
||||
"extension). Options may also be included following a pipe symbol. The only\n"
|
||||
"defined option at this time is 'skip', which causes the playback of the\n"
|
||||
"message to be skipped if the channel is not in the 'up' state (i.e. it\n"
|
||||
"hasn't been answered yet. If 'skip' is not specified, the channel will be\n"
|
||||
"answered before the sound is played. Returns -1 if the channel was hung up,\n"
|
||||
"or if the file does not exist. Returns 0 otherwise.\n";
|
||||
"hasn't been answered yet. If 'skip' is specified, the application will\n"
|
||||
"return immediately should the channel not be off hook. Otherwise, unless\n"
|
||||
"'noanswer' is specified, the channel channel will be answered before the sound\n"
|
||||
"is played. Not all channels support playing messages while on hook. Returns -1\n"
|
||||
"if the channel was hung up, or if the file does not exist. Returns 0 otherwise.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -47,23 +50,26 @@ static int playback_exec(struct ast_channel *chan, void *data)
|
||||
char tmp[256];
|
||||
char *options;
|
||||
int option_skip=0;
|
||||
int option_noanswer = 0;
|
||||
if (!data || !strlen((char *)data)) {
|
||||
ast_log(LOG_WARNING, "Playback requires an argument (filename)\n");
|
||||
return -1;
|
||||
}
|
||||
strncpy(tmp, (char *)data, sizeof(tmp));
|
||||
strncpy(tmp, (char *)data, sizeof(tmp)-1);
|
||||
strtok(tmp, "|");
|
||||
options = strtok(NULL, "|");
|
||||
if (options && !strcasecmp(options, "skip"))
|
||||
option_skip = 1;
|
||||
if (options && !strcasecmp(options, "noanswer"))
|
||||
option_noanswer = 1;
|
||||
LOCAL_USER_ADD(u);
|
||||
if (chan->state != AST_STATE_UP) {
|
||||
if (option_skip) {
|
||||
/* At the user's option, skip if the line is not up */
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
} else
|
||||
/* Otherwise answer */
|
||||
} else if (!option_noanswer)
|
||||
/* Otherwise answer unless we're supposed to send this while on-hook */
|
||||
res = ast_answer(chan);
|
||||
}
|
||||
if (!res) {
|
||||
|
||||
384
apps/app_qcall.c
Normal file
384
apps/app_qcall.c
Normal file
@@ -0,0 +1,384 @@
|
||||
/** @file app_qcall.c
|
||||
*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Call back a party and connect them to a running pbx thread
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*
|
||||
* Call a user from a file contained within a queue (/var/spool/asterisk/qcall)
|
||||
*
|
||||
* The queue is a directory containing files with the call request information
|
||||
* as a single line of text as follows:
|
||||
*
|
||||
* Dialstring Caller-ID Extension Maxsecs [Identifier] [Required-response]
|
||||
*
|
||||
* Dialstring -- A Dial String (The number to be called) in the
|
||||
* format Technology/Number, such IAX/mysys/1234 or Zap/g1/1234
|
||||
*
|
||||
* Caller-ID -- A Standard nomalized representation of the Caller-ID of
|
||||
* the number being dialed (generally 10 digits in the US). Leave as
|
||||
* "asreceived" to use the default Caller*ID
|
||||
*
|
||||
* Extension -- The Extension (optionally Extension@context) that the
|
||||
* user should be "transferred" to after acceptance of the call.
|
||||
*
|
||||
* Maxsecs -- The Maximum time of the call in seconds. Specify 0 for infinite.
|
||||
*
|
||||
* Identifier -- The "Identifier" of the request. This is used to determine
|
||||
* the names of the audio prompt files played. The first prompt, the one that
|
||||
* asks for the input, is just the exact string specified as the identifier.
|
||||
* The second prompt, the one that is played after the correct input is given,
|
||||
* (generally a "thank you" recording), is the specified string with "-ok"
|
||||
* added to the end. So, if you specify "foo" as the identifier, your first
|
||||
* prompt file that will be played will be "foo" and the second one will be
|
||||
* "foo-ok". If omitted no prompt is given
|
||||
*
|
||||
* Required-Response (Optional) -- Specify a digit string to be used as the
|
||||
* acceptance "code" if you desire it to be something other then "1". This
|
||||
* can be used to implement some sort of PIN or security system. It may be
|
||||
* more then a single character.
|
||||
*
|
||||
* NOTE: It is important to remember that the process that creates these
|
||||
* files needs keep and maintain a write lock (using flock with the LOCK_EX
|
||||
* option) when writing these files.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <dirent.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/file.h>
|
||||
|
||||
const char *qdir="/var/spool/asterisk/qcall";
|
||||
static char *tdesc = "Call from Queue";
|
||||
static pthread_t qcall_thread;
|
||||
static int debug = 0;
|
||||
STANDARD_LOCAL_USER;
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
#define OLDESTOK 14400 /* not any more then this number of secs old */
|
||||
#define INITIALONE 1 /* initial wait before the first one in secs */
|
||||
#define NEXTONE 600 /* wait before trying it again in secs */
|
||||
#define MAXWAITFORANSWER 45000 /* max call time before answer */
|
||||
/* define either one or both of these two if your application requires it */
|
||||
#if 0
|
||||
#define ACCTCODE "SOMETHING" /* Account code */
|
||||
#define AMAFLAGS AST_CDR_BILLING /* AMA flags */
|
||||
#endif
|
||||
/* define this if you want to have a particular CLID display on the user's
|
||||
phone when they receive the call */
|
||||
#if 0
|
||||
#define OURCLID "2564286275" /* The callerid to be displayed when calling */
|
||||
#endif
|
||||
|
||||
static void *qcall_do(void *arg);
|
||||
|
||||
static void *qcall(void *ignore)
|
||||
{
|
||||
pthread_t dialer_thread;
|
||||
DIR *dirp;
|
||||
FILE *fp;
|
||||
struct dirent *dp;
|
||||
char fname[80];
|
||||
struct stat mystat;
|
||||
time_t t;
|
||||
void *arg;
|
||||
pthread_attr_t attr;
|
||||
|
||||
time(&t);
|
||||
if (debug) printf("@@@@ qcall starting at %s",ctime(&t));
|
||||
for(;;)
|
||||
{
|
||||
time(&t);
|
||||
dirp = opendir(qdir);
|
||||
if (!dirp)
|
||||
{
|
||||
perror("app_qcall:Cannot open queue directory");
|
||||
break;
|
||||
}
|
||||
while((dp = readdir(dirp)) != NULL)
|
||||
{
|
||||
if (dp->d_name[0] == '.') continue;
|
||||
sprintf(fname,"%s/%s",qdir,dp->d_name);
|
||||
if (stat(fname,&mystat) == -1)
|
||||
{
|
||||
perror("app_qcall:stat");
|
||||
fprintf(stderr,"%s\n",fname);
|
||||
continue;
|
||||
}
|
||||
/* if not a regular file, skip it */
|
||||
if ((mystat.st_mode & S_IFMT) != S_IFREG) continue;
|
||||
/* if not yet .... */
|
||||
if (mystat.st_atime == mystat.st_ctime)
|
||||
{ /* first time */
|
||||
if ((mystat.st_atime + INITIALONE) > t)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{ /* already looked at once */
|
||||
if ((mystat.st_atime + NEXTONE) > t) continue;
|
||||
}
|
||||
/* if too old */
|
||||
if (mystat.st_mtime < (t - OLDESTOK))
|
||||
{
|
||||
/* kill it, its too old */
|
||||
unlink(fname);
|
||||
continue;
|
||||
}
|
||||
/* "touch" file's access time */
|
||||
fp = fopen(fname,"r");
|
||||
if (fp) fclose(fp);
|
||||
/* make a copy of the filename string, so that we
|
||||
may go on and use the buffer */
|
||||
arg = (void *) strdup(fname);
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
if (pthread_create(&dialer_thread,&attr,qcall_do,arg) == -1)
|
||||
{
|
||||
perror("qcall: Cannot create thread");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
closedir(dirp);
|
||||
sleep(1);
|
||||
}
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
/* single thread with one file (request) to dial */
|
||||
static void *qcall_do(void *arg)
|
||||
{
|
||||
char fname[300],dialstr[300],extstr[300],ident[300],reqinp[300],buf[300];
|
||||
char clid[300],*tele,*context;
|
||||
FILE *fp;
|
||||
int ms = MAXWAITFORANSWER,maxsecs;
|
||||
struct ast_channel *channel;
|
||||
time_t t;
|
||||
|
||||
/* get the filename from the arg */
|
||||
strcpy(fname,(char *)arg);
|
||||
free(arg);
|
||||
time(&t);
|
||||
fp = fopen(fname,"r");
|
||||
if (!fp) /* if cannot open request file */
|
||||
{
|
||||
perror("qcall_do:fopen");
|
||||
fprintf(stderr,"%s\n",fname);
|
||||
unlink(fname);
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
/* lock the file */
|
||||
if (flock(fileno(fp),LOCK_EX) == -1)
|
||||
{
|
||||
perror("qcall_do:flock");
|
||||
fprintf(stderr,"%s\n",fname);
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
strcpy(reqinp,"1"); /* default required input for acknowledgement */
|
||||
strcpy(ident, ""); /* default no ident */
|
||||
if (fscanf(fp,"%s %s %s %d %s %s",dialstr,clid,
|
||||
extstr,&maxsecs,ident,reqinp) < 4)
|
||||
{
|
||||
fprintf(stderr,"qcall_do:file line invalid in file %s:\n",fname);
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
flock(fileno(fp),LOCK_UN);
|
||||
fclose(fp);
|
||||
tele = strchr(dialstr,'/');
|
||||
if (!tele)
|
||||
{
|
||||
fprintf(stderr,"qcall_do:Dial number must be in format tech/number\n");
|
||||
unlink(fname);
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
*tele++ = 0;
|
||||
channel = ast_request(dialstr,AST_FORMAT_SLINEAR,tele);
|
||||
if (channel)
|
||||
{
|
||||
ast_set_read_format(channel,AST_FORMAT_SLINEAR);
|
||||
ast_set_write_format(channel,AST_FORMAT_SLINEAR);
|
||||
#ifdef OURCLID
|
||||
if (channel->callerid)
|
||||
free(channel->callerid);
|
||||
channel->callerid = strdup(OURCLID);
|
||||
if (channel->ani)
|
||||
free(channel->ani);
|
||||
channel->ani = strdup(OURCLID);
|
||||
#endif
|
||||
channel->whentohangup = 0;
|
||||
channel->appl = "AppQcall";
|
||||
channel->data = "(Outgoing Line)";
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Qcall initiating call to %s/%s on %s (%s)\n",
|
||||
dialstr,tele,channel->name,fname);
|
||||
ast_call(channel,tele,MAXWAITFORANSWER);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"qcall_do:Sorry unable to obtain channel\n");
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
if (strcasecmp(clid, "asreceived")) {
|
||||
if (channel->callerid) free(channel->callerid);
|
||||
channel->callerid = NULL;
|
||||
if (channel->ani) free(channel->ani);
|
||||
channel->ani = NULL;
|
||||
}
|
||||
if (channel->state == AST_STATE_UP)
|
||||
if (debug) printf("@@@@ Autodial:Line is Up\n");
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Qcall waiting for answer on %s\n",
|
||||
channel->name);
|
||||
while(ms > 0){
|
||||
struct ast_frame *f;
|
||||
ms = ast_waitfor(channel,ms);
|
||||
f = ast_read(channel);
|
||||
if (!f)
|
||||
{
|
||||
if (debug) printf("@@@@ qcall_do:Hung Up\n");
|
||||
unlink(fname);
|
||||
break;
|
||||
}
|
||||
if (f->frametype == AST_FRAME_CONTROL)
|
||||
{
|
||||
if (f->subclass == AST_CONTROL_HANGUP)
|
||||
{
|
||||
if (debug) printf("@@@@ qcall_do:Hung Up\n");
|
||||
unlink(fname);
|
||||
ast_frfree(f);
|
||||
break;
|
||||
}
|
||||
if (f->subclass == AST_CONTROL_ANSWER)
|
||||
{
|
||||
if (debug) printf("@@@@ qcall_do:Phone Answered\n");
|
||||
if (channel->state == AST_STATE_UP)
|
||||
{
|
||||
unlink(fname);
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Qcall got answer on %s\n",
|
||||
channel->name);
|
||||
usleep(1500000);
|
||||
if (strlen(ident)) {
|
||||
ast_streamfile(channel,ident,0);
|
||||
if (ast_readstring(channel,buf,strlen(reqinp),10000,5000,"#"))
|
||||
{
|
||||
ast_stopstream(channel);
|
||||
if (debug) printf("@@@@ qcall_do: timeout or hangup in dtmf read\n");
|
||||
ast_frfree(f);
|
||||
break;
|
||||
}
|
||||
ast_stopstream(channel);
|
||||
if (strcmp(buf,reqinp)) /* if not match */
|
||||
{
|
||||
if (debug) printf("@@@@ qcall_do: response (%s) does not match required (%s)\n",buf,reqinp);
|
||||
ast_frfree(f);
|
||||
break;
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
/* okay, now we go for it */
|
||||
context = strchr(extstr,'@');
|
||||
if (!context) context = "default";
|
||||
else *context++ = 0;
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Qcall got accept, now putting through to %s@%s on %s\n",
|
||||
extstr,context,channel->name);
|
||||
if (strlen(ident)) {
|
||||
strcat(ident,"-ok");
|
||||
/* if file existant, play it */
|
||||
if (!ast_streamfile(channel,ident,0))
|
||||
{
|
||||
ast_waitstream(channel,"");
|
||||
ast_stopstream(channel);
|
||||
}
|
||||
}
|
||||
if (strcasecmp(clid, "asreceived")) {
|
||||
channel->callerid = strdup(clid);
|
||||
channel->ani = strdup(clid);
|
||||
}
|
||||
channel->language[0] = 0;
|
||||
channel->dnid = strdup(extstr);
|
||||
#ifdef AMAFLAGS
|
||||
channel->amaflags = AMAFLAGS;
|
||||
#endif
|
||||
#ifdef ACCTCODE
|
||||
strcpy(channel->accountcode,ACCTCODE);
|
||||
#else
|
||||
channel->accountcode[0] = 0;
|
||||
#endif
|
||||
if (maxsecs) /* if finite length call */
|
||||
{
|
||||
time(&channel->whentohangup);
|
||||
channel->whentohangup += maxsecs;
|
||||
}
|
||||
strcpy(channel->exten,extstr);
|
||||
strcpy(channel->context,context);
|
||||
channel->priority = 1;
|
||||
printf("Caller ID is %s\n", channel->callerid);
|
||||
ast_pbx_run(channel);
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
}
|
||||
else if(f->subclass==AST_CONTROL_RINGING)
|
||||
if (debug) printf("@@@@ qcall_do:Phone Ringing end\n");
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
ast_hangup(channel);
|
||||
if (debug) printf("@@@@ qcall_do:Hung up channel\n");
|
||||
pthread_exit(NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
mkdir(qdir,0660);
|
||||
pthread_create(&qcall_thread,NULL,qcall,NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
@@ -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>
|
||||
@@ -51,7 +52,7 @@ static int record_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
struct ast_filestream *s = '\0';
|
||||
struct localuser *u;
|
||||
struct ast_frame *f;
|
||||
struct ast_frame *f = NULL;
|
||||
|
||||
vdata = data; /* explained above */
|
||||
|
||||
@@ -89,7 +90,7 @@ static int record_exec(struct ast_channel *chan, void *data)
|
||||
count++;
|
||||
} while ( ast_fileexists(tmp, ext, chan->language) != -1 );
|
||||
} else
|
||||
strncpy(tmp, fil, 256);
|
||||
strncpy(tmp, fil, 256-1);
|
||||
/* end of routine mentioned */
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
@@ -103,10 +104,8 @@ static int record_exec(struct ast_channel *chan, void *data)
|
||||
/* Some code to play a nice little beep to signify the start of the record operation */
|
||||
res = ast_streamfile(chan, "beep", chan->language);
|
||||
if (!res) {
|
||||
printf("Waiting on stream\n");
|
||||
res = ast_waitstream(chan, "");
|
||||
} else {
|
||||
printf("streamfile failed\n");
|
||||
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", chan->name);
|
||||
}
|
||||
ast_stopstream(chan);
|
||||
@@ -114,8 +113,12 @@ static int record_exec(struct ast_channel *chan, void *data)
|
||||
s = ast_writefile( tmp, ext, NULL, O_CREAT|O_TRUNC|O_WRONLY , 0, 0644);
|
||||
|
||||
if (s) {
|
||||
|
||||
while ((f = ast_read(chan))) {
|
||||
while (ast_waitfor(chan, -1) > -1) {
|
||||
f = ast_read(chan);
|
||||
if (!f) {
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
res = ast_writestream(s, f);
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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>
|
||||
@@ -55,7 +56,7 @@ static int sendurl_exec(struct ast_channel *chan, void *data)
|
||||
ast_log(LOG_WARNING, "SendURL requires an argument (URL)\n");
|
||||
return -1;
|
||||
}
|
||||
strncpy(tmp, (char *)data, sizeof(tmp));
|
||||
strncpy(tmp, (char *)data, sizeof(tmp)-1);
|
||||
strtok(tmp, "|");
|
||||
options = strtok(NULL, "|");
|
||||
if (options && !strcasecmp(options, "wait"))
|
||||
|
||||
1053
apps/app_voicemail.c
1053
apps/app_voicemail.c
File diff suppressed because it is too large
Load Diff
91
apps/app_zapateller.c
Normal file
91
apps/app_zapateller.c
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Playback the special information tone to get rid of telemarketers
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Block Telemarketers with Special Information Tone";
|
||||
|
||||
static char *app = "Zapateller";
|
||||
|
||||
static char *synopsis = "Block telemarketers with SIT";
|
||||
|
||||
static char *descrip =
|
||||
" Zapateller(options): Generates special information tone to block telemarketers\n"
|
||||
"from calling you. Returns 0 normally or -1 on hangup. Options is a pipe-delimited\n"
|
||||
"list of options. The only supported option is 'answer' which will cause the line to\n"
|
||||
"be answered before playing the tone";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int zapateller_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
struct localuser *u;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
ast_stopstream(chan);
|
||||
if (chan->state != AST_STATE_UP) {
|
||||
if (data && !strcasecmp(data, "answer"))
|
||||
res = ast_answer(chan);
|
||||
if (!res) {
|
||||
res = ast_safe_sleep(chan, 500);
|
||||
}
|
||||
}
|
||||
if (!res)
|
||||
res = ast_tonepair(chan, 950, 0, 330, 0);
|
||||
if (!res)
|
||||
res = ast_tonepair(chan, 1400, 0, 330, 0);
|
||||
if (!res)
|
||||
res = ast_tonepair(chan, 1800, 0, 330, 0);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, zapateller_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
238
apps/app_zapras.c
Normal file
238
apps/app_zapras.c
Normal file
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Execute an ISDN RAS
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/signal.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
/* Need some zaptel help here */
|
||||
#include <linux/zaptel.h>
|
||||
|
||||
static char *tdesc = "Zap RAS Application";
|
||||
|
||||
static char *app = "ZapRAS";
|
||||
|
||||
static char *synopsis = "Executes Zaptel ISDN RAS application";
|
||||
|
||||
static char *descrip =
|
||||
" ZapRAS(args): Executes a RAS server using pppd on the given channel.\n"
|
||||
"The channel must be a clear channel (i.e. PRI source) and a Zaptel\n"
|
||||
"channel to be able to use this function (No modem emulcation is included).\n"
|
||||
"Your pppd must be patched to be zaptel aware. Arguments should be\n"
|
||||
"separated by | characters. Always returns -1.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
#define PPP_MAX_ARGS 32
|
||||
#define PPP_EXEC "/usr/sbin/pppd"
|
||||
|
||||
static pid_t spawn_ras(struct ast_channel *chan, char *args)
|
||||
{
|
||||
pid_t pid;
|
||||
int x;
|
||||
char *c;
|
||||
|
||||
char *argv[PPP_MAX_ARGS];
|
||||
int argc = 0;
|
||||
|
||||
/* Start by forking */
|
||||
pid = fork();
|
||||
if (pid)
|
||||
return pid;
|
||||
|
||||
/* Execute RAS on File handles */
|
||||
dup2(chan->fds[0], STDIN_FILENO);
|
||||
|
||||
/* Close other file descriptors */
|
||||
for (x=STDERR_FILENO + 1;x<1024;x++)
|
||||
close(x);
|
||||
|
||||
/* Restore original signal handlers */
|
||||
for (x=0;x<NSIG;x++)
|
||||
signal(x, SIG_DFL);
|
||||
|
||||
/* Reset all arguments */
|
||||
memset(argv, 0, sizeof(argv));
|
||||
|
||||
/* First argument is executable, followed by standard
|
||||
arguments for zaptel PPP */
|
||||
argv[argc++] = PPP_EXEC;
|
||||
argv[argc++] = "nodetach";
|
||||
|
||||
/* And all the other arguments */
|
||||
c = strtok(args, "|");
|
||||
while(c && strlen(c) && (argc < (PPP_MAX_ARGS - 4))) {
|
||||
argv[argc++] = c;
|
||||
c = strtok(NULL, "|");
|
||||
}
|
||||
|
||||
argv[argc++] = "plugin";
|
||||
argv[argc++] = "zaptel.so";
|
||||
argv[argc++] = "stdin";
|
||||
|
||||
#if 0
|
||||
for (x=0;x<argc;x++) {
|
||||
fprintf(stderr, "Arg %d: %s\n", x, argv[x]);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Finally launch PPP */
|
||||
execv(PPP_EXEC, argv);
|
||||
fprintf(stderr, "Failed to exec PPPD!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void run_ras(struct ast_channel *chan, char *args)
|
||||
{
|
||||
pid_t pid;
|
||||
int status;
|
||||
int res;
|
||||
int signalled = 0;
|
||||
struct zt_bufferinfo bi;
|
||||
int x;
|
||||
|
||||
pid = spawn_ras(chan, args);
|
||||
if (pid < 0) {
|
||||
ast_log(LOG_WARNING, "Failed to spawn RAS\n");
|
||||
} else {
|
||||
for (;;) {
|
||||
res = wait4(pid, &status, WNOHANG, NULL);
|
||||
if (!res) {
|
||||
/* Check for hangup */
|
||||
if (chan->softhangup && !signalled) {
|
||||
ast_log(LOG_DEBUG, "Channel '%s' hungup. Signalling RAS at %d to die...\n", chan->name, pid);
|
||||
kill(pid, SIGTERM);
|
||||
signalled=1;
|
||||
}
|
||||
/* Try again */
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "wait4 returned %d: %s\n", res, strerror(errno));
|
||||
}
|
||||
if (option_verbose > 2) {
|
||||
if (WIFEXITED(status)) {
|
||||
ast_verbose(VERBOSE_PREFIX_3 "RAS on %s terminated with status %d\n", chan->name, WEXITSTATUS(status));
|
||||
} else if (WIFSIGNALED(status)) {
|
||||
ast_verbose(VERBOSE_PREFIX_3 "RAS on %s terminated with signal %d\n",
|
||||
chan->name, WTERMSIG(status));
|
||||
} else {
|
||||
ast_verbose(VERBOSE_PREFIX_3 "RAS on %s terminated weirdly.\n", chan->name);
|
||||
}
|
||||
}
|
||||
/* Throw back into audio mode */
|
||||
x = 1;
|
||||
ioctl(chan->fds[0], ZT_AUDIOMODE, &x);
|
||||
|
||||
/* Double check buffering too */
|
||||
res = ioctl(chan->fds[0], ZT_GET_BUFINFO, &bi);
|
||||
if (!res) {
|
||||
/* XXX This is ZAP_BLOCKSIZE XXX */
|
||||
bi.bufsize = 204;
|
||||
bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
|
||||
bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
|
||||
bi.numbufs = 4;
|
||||
res = ioctl(chan->fds[0], ZT_SET_BUFINFO, &bi);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to set buffer policy on channel %s\n", chan->name);
|
||||
}
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Unable to check buffer policy on channel %s\n", chan->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int zapras_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=-1;
|
||||
char args[256];
|
||||
struct localuser *u;
|
||||
ZT_PARAMS ztp;
|
||||
|
||||
if (!data)
|
||||
data = "";
|
||||
LOCAL_USER_ADD(u);
|
||||
strncpy(args, data, sizeof(args) - 1);
|
||||
/* Answer the channel if it's not up */
|
||||
if (chan->state != AST_STATE_UP)
|
||||
ast_answer(chan);
|
||||
if (strcasecmp(chan->type, "Zap")) {
|
||||
/* If it's not a zap channel, we're done. Wait a couple of
|
||||
seconds and then hangup... */
|
||||
if (option_verbose > 1)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "Channel %s is not a Zap channel\n", chan->name);
|
||||
sleep(2);
|
||||
} else {
|
||||
memset(&ztp, 0, sizeof(ztp));
|
||||
if (ioctl(chan->fds[0], ZT_GET_PARAMS, &ztp)) {
|
||||
ast_log(LOG_WARNING, "Unable to get zaptel parameters\n");
|
||||
} else if (ztp.sigtype != ZT_SIG_CLEAR) {
|
||||
if (option_verbose > 1)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "Channel %s is not a clear channel\n", chan->name);
|
||||
} else {
|
||||
/* Everything should be okay. Run PPP. */
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Starting RAS on %s\n", chan->name);
|
||||
/* Execute RAS */
|
||||
run_ras(chan, args);
|
||||
}
|
||||
}
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, zapras_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
287
apps/enter.h
Normal file
287
apps/enter.h
Normal file
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
* U-law 8-bit audio data
|
||||
*
|
||||
* Source: enter.raw
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer and Linux Support Services
|
||||
*
|
||||
* Distributed under the terms of the GNU General Public License
|
||||
*
|
||||
*/
|
||||
|
||||
static unsigned char enter[] = {
|
||||
0xba, 0xba, 0xb0, 0xa6, 0xa9, 0xb8, 0xfe, 0x46, 0x42, 0x46,
|
||||
0x4a, 0xfe, 0xac, 0xa2, 0x9f, 0x9f, 0xa8, 0xb8, 0x3b, 0x29,
|
||||
0x35, 0x4a, 0xfe, 0xc1, 0xad, 0xa2, 0xad, 0xc5, 0x4e, 0x68,
|
||||
0x68, 0xe7, 0xb8, 0xb0, 0xb2, 0xc1, 0xc1, 0xb0, 0xae, 0xcd,
|
||||
0xfe, 0xfe, 0xcd, 0xcd, 0xfe, 0x68, 0xd3, 0xb2, 0xae, 0xab,
|
||||
0xb2, 0xfe, 0x35, 0x31, 0xdb, 0xac, 0xab, 0xaf, 0xab, 0xaa,
|
||||
0xb4, 0x68, 0x3b, 0x39, 0x3f, 0x68, 0xb4, 0xa8, 0xa8, 0xb0,
|
||||
0xbc, 0xbc, 0xc5, 0x3f, 0x31, 0x37, 0xfe, 0xc1, 0xbc, 0xb0,
|
||||
0xa5, 0xa2, 0xa8, 0xaf, 0xbe, 0x3b, 0x28, 0x26, 0x3d, 0xbc,
|
||||
0xb0, 0xae, 0xa2, 0x9f, 0xa2, 0xfe, 0x29, 0x24, 0x29, 0x4a,
|
||||
0xc5, 0xaa, 0xa8, 0xa9, 0xa8, 0xa5, 0xa7, 0xdb, 0x2c, 0x27,
|
||||
0x2d, 0x4a, 0xfe, 0xdb, 0xb2, 0xa2, 0x9f, 0x9f, 0xae, 0xe7,
|
||||
0x2c, 0x22, 0x2b, 0xfe, 0xba, 0xb0, 0xaa, 0x9f, 0xa3, 0xb0,
|
||||
0x5c, 0x33, 0x33, 0x39, 0x5c, 0xdb, 0xc1, 0xb4, 0xb0, 0xaa,
|
||||
0xad, 0xba, 0x54, 0x46, 0xfe, 0xe7, 0xfe, 0x54, 0xe7, 0xaf,
|
||||
0xa6, 0xa7, 0xb0, 0xfe, 0x46, 0x39, 0x5c, 0xe7, 0xdb, 0xfe,
|
||||
0xba, 0xac, 0xa8, 0xc5, 0x46, 0x33, 0x54, 0xc5, 0xae, 0xad,
|
||||
0xb2, 0xc1, 0xcd, 0xc1, 0xbc, 0xfe, 0x3f, 0x37, 0xfe, 0xb4,
|
||||
0xb6, 0xcd, 0xdb, 0xc1, 0xb0, 0xb6, 0xcd, 0x4e, 0x39, 0x37,
|
||||
0xfe, 0xb0, 0xab, 0xa9, 0xa9, 0xa9, 0xb0, 0x5c, 0x29, 0x25,
|
||||
0x31, 0xfe, 0xc1, 0xb4, 0xae, 0xab, 0xab, 0xb2, 0xcd, 0x3b,
|
||||
0x2a, 0x2c, 0x54, 0xb4, 0xb4, 0xba, 0xb2, 0xa3, 0x9f, 0xa8,
|
||||
0xfe, 0x33, 0x27, 0x2a, 0x39, 0xfe, 0xc1, 0xbe, 0xb0, 0xa2,
|
||||
0x9f, 0xb0, 0x33, 0x22, 0x25, 0x46, 0xc1, 0xb8, 0xb0, 0xab,
|
||||
0xa8, 0xa8, 0xb0, 0xbe, 0x42, 0x2c, 0x2e, 0x4a, 0xfe, 0x5c,
|
||||
0xfe, 0xb4, 0xa8, 0xa8, 0xba, 0xfe, 0x4a, 0x39, 0x39, 0x46,
|
||||
0xfe, 0xbc, 0xaf, 0xa5, 0xa5, 0xae, 0x68, 0x37, 0x4a, 0xfe,
|
||||
0xfe, 0x4a, 0x4a, 0xd3, 0xb0, 0xb0, 0xc1, 0x5c, 0x46, 0x46,
|
||||
0xd3, 0xb6, 0xbe, 0x54, 0x54, 0xc9, 0xab, 0xae, 0xc5, 0x46,
|
||||
0x4a, 0xfe, 0xcd, 0xc9, 0xcd, 0xe7, 0xe7, 0xc9, 0xb4, 0xc5,
|
||||
0x4a, 0x2c, 0x37, 0xc1, 0xb0, 0xb2, 0xb4, 0xb2, 0xb6, 0xdb,
|
||||
0xfe, 0x4a, 0x46, 0x3f, 0x68, 0xba, 0xb2, 0xba, 0xc5, 0xb6,
|
||||
0xb2, 0xcd, 0x33, 0x2e, 0x39, 0x68, 0xfe, 0xe7, 0xba, 0xaf,
|
||||
0xa7, 0xa7, 0xad, 0xe7, 0x2d, 0x25, 0x2f, 0xd3, 0xbe, 0xcd,
|
||||
0xc5, 0xac, 0xa6, 0xac, 0xfe, 0x3b, 0x2c, 0x2d, 0x3d, 0xc1,
|
||||
0xb4, 0xbe, 0xcd, 0xaf, 0xa5, 0xa8, 0xe7, 0x31, 0x2f, 0x39,
|
||||
0x46, 0x5c, 0xdb, 0xbc, 0xba, 0xaf, 0xa9, 0xad, 0xfe, 0x2f,
|
||||
0x2d, 0xba, 0xad, 0xba, 0xfe, 0x3d, 0x42, 0x5c, 0xc9, 0xc1,
|
||||
0xcd, 0xfe, 0xc1, 0xae, 0xa6, 0xcd, 0x33, 0x25, 0x3b, 0xdb,
|
||||
0xb0, 0xb6, 0xb8, 0xb6, 0xb4, 0xb8, 0xba, 0xfe, 0x3d, 0x37,
|
||||
0xfe, 0xba, 0xc1, 0x54, 0x54, 0xd3, 0xb0, 0xb4, 0xe7, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xd3, 0xb6, 0xa9, 0xa7, 0xba,
|
||||
0x3d, 0x35, 0xfe, 0xc1, 0xcd, 0x4a, 0x54, 0xbe, 0xb2, 0xb8,
|
||||
0xfe, 0x46, 0x3b, 0xfe, 0xba, 0xab, 0xc5, 0x46, 0x3b, 0xbc,
|
||||
0xaa, 0xab, 0xd3, 0x68, 0xfe, 0xd3, 0xcd, 0xdb, 0x54, 0x3d,
|
||||
0x4a, 0xbc, 0xac, 0xb4, 0x3f, 0x2e, 0x3d, 0xba, 0xb0, 0xb8,
|
||||
0xba, 0xb6, 0xba, 0xcd, 0xfe, 0xfe, 0x5c, 0x54, 0xc9, 0xb4,
|
||||
0xbe, 0x54, 0x54, 0xcd, 0xb6, 0xc9, 0x46, 0x54, 0xcd, 0xc5,
|
||||
0xdb, 0xfe, 0xfe, 0xc1, 0xae, 0xa9, 0xac, 0xfe, 0x35, 0x2e,
|
||||
0xfe, 0xba, 0xc1, 0x5c, 0xfe, 0xb6, 0xaa, 0xb0, 0xe7, 0x35,
|
||||
0x2e, 0x39, 0xc1, 0xac, 0xb0, 0xfe, 0xfe, 0xbc, 0xa6, 0xac,
|
||||
0xc1, 0x42, 0x46, 0x54, 0xfe, 0xfe, 0xfe, 0xfe, 0xc9, 0xae,
|
||||
0xa9, 0xb0, 0x54, 0x35, 0x37, 0xfe, 0xd3, 0xd3, 0xb8, 0xae,
|
||||
0xab, 0xb6, 0xe7, 0xfe, 0xfe, 0x68, 0xfe, 0xfe, 0xfe, 0x4e,
|
||||
0xfe, 0xb0, 0xac, 0xb8, 0xfe, 0xfe, 0xc1, 0xb6, 0xc5, 0x46,
|
||||
0x3d, 0xe7, 0xb4, 0xa7, 0xab, 0xbc, 0x3f, 0x37, 0x54, 0xba,
|
||||
0xcd, 0x54, 0x42, 0xc5, 0xae, 0xac, 0xc9, 0x46, 0x3d, 0x54,
|
||||
0xba, 0xb0, 0xb0, 0xfe, 0x5c, 0xcd, 0xb0, 0xb0, 0xc9, 0x54,
|
||||
0x54, 0xfe, 0xfe, 0xfe, 0xfe, 0xe7, 0xcd, 0xc1, 0xba, 0xc5,
|
||||
0xfe, 0x42, 0x46, 0xfe, 0xc5, 0xba, 0xb2, 0xa7, 0xa7, 0xb0,
|
||||
0xfe, 0x3d, 0x4a, 0x5c, 0xfe, 0xfe, 0xfe, 0xe7, 0xbc, 0xb0,
|
||||
0xae, 0xc5, 0x4e, 0x39, 0xfe, 0xc5, 0xbe, 0xfe, 0x54, 0xc9,
|
||||
0xa9, 0xa2, 0xa5, 0xbc, 0x3b, 0x2f, 0x35, 0xfe, 0xc9, 0xfe,
|
||||
0xfe, 0xc5, 0xa9, 0xa6, 0xb0, 0x54, 0x31, 0x31, 0x3f, 0xd3,
|
||||
0xbc, 0xc1, 0xcd, 0xb8, 0xae, 0xa8, 0xb4, 0xd3, 0x54, 0x4e,
|
||||
0x5c, 0x54, 0xfe, 0xdb, 0xba, 0xb4, 0xb4, 0xba, 0xcd, 0x5c,
|
||||
0x3d, 0x3f, 0x54, 0xfe, 0xcd, 0xaf, 0xa8, 0xac, 0xc5, 0xfe,
|
||||
0xfe, 0xe7, 0xdb, 0xfe, 0xfe, 0xfe, 0xe7, 0xb8, 0xaf, 0xb0,
|
||||
0xe7, 0x42, 0x4a, 0xcd, 0xbc, 0xdb, 0x46, 0x68, 0xcd, 0xb0,
|
||||
0xab, 0xbc, 0xfe, 0x3d, 0x46, 0xfe, 0xb8, 0xbc, 0xd3, 0xd3,
|
||||
0xb6, 0xb0, 0xb6, 0x5c, 0x3b, 0x35, 0x54, 0xdb, 0xba, 0xb4,
|
||||
0xc1, 0xc9, 0xc1, 0xba, 0xc9, 0x5c, 0x3d, 0x46, 0xfe, 0xcd,
|
||||
0xc5, 0xb8, 0xae, 0xaf, 0xb4, 0xd3, 0x54, 0x3d, 0x35, 0x46,
|
||||
0xfe, 0xdb, 0xbc, 0xb2, 0xa9, 0xab, 0xba, 0x3f, 0x31, 0x39,
|
||||
0xfe, 0xe7, 0xdb, 0xcd, 0xb8, 0xae, 0xab, 0xac, 0xe7, 0x3d,
|
||||
0x2d, 0x3f, 0xfe, 0xdb, 0xfe, 0xfe, 0xbc, 0xaa, 0xa8, 0xb0,
|
||||
0xfe, 0x31, 0x2d, 0x3d, 0xdb, 0xc5, 0xcd, 0xc9, 0xb4, 0xa8,
|
||||
0xad, 0xc5, 0x46, 0x39, 0x3f, 0x5c, 0xfe, 0xd3, 0xc5, 0xc1,
|
||||
0xb6, 0xb0, 0xbc, 0x68, 0x46, 0x4e, 0xe7, 0xfe, 0x5c, 0xfe,
|
||||
0xc1, 0xaf, 0xb0, 0xb8, 0xe7, 0x5c, 0x5c, 0xfe, 0xe7, 0xfe,
|
||||
0xfe, 0xe7, 0xb0, 0xab, 0xb2, 0x4a, 0x37, 0x3f, 0xcd, 0xbe,
|
||||
0xc1, 0xe7, 0xe7, 0xd3, 0xb6, 0xb4, 0xc9, 0x3b, 0x33, 0x4a,
|
||||
0xba, 0xb4, 0xc5, 0xfe, 0xc9, 0xb6, 0xb4, 0xcd, 0xfe, 0x3b,
|
||||
0x3b, 0xfe, 0xc1, 0xb6, 0xc5, 0xc5, 0xb8, 0xb0, 0xba, 0x4a,
|
||||
0x31, 0x35, 0x68, 0xcd, 0xc5, 0xba, 0xb4, 0xb0, 0xb0, 0xba,
|
||||
0x5c, 0x35, 0x2f, 0x4e, 0xd3, 0xc1, 0xdb, 0xd3, 0xb4, 0xa9,
|
||||
0xab, 0xcd, 0x3b, 0x2f, 0x35, 0xfe, 0xd3, 0xd3, 0xdb, 0xbc,
|
||||
0xad, 0xa4, 0xb0, 0xfe, 0x2d, 0x2f, 0x3f, 0xe7, 0xe7, 0xe7,
|
||||
0xcd, 0xb4, 0xaf, 0xad, 0xc5, 0x3d, 0x31, 0x3d, 0xe7, 0xd3,
|
||||
0xe7, 0xe7, 0xc1, 0xaf, 0xad, 0xb6, 0xfe, 0x4a, 0x42, 0x54,
|
||||
0xfe, 0x68, 0xfe, 0xd3, 0xb2, 0xae, 0xb4, 0xfe, 0x42, 0x4e,
|
||||
0xcd, 0xc5, 0xcd, 0xdb, 0xc9, 0xb4, 0xb0, 0xb6, 0xfe, 0x3b,
|
||||
0x42, 0xe7, 0xb0, 0xb8, 0xcd, 0xfe, 0xc9, 0xb6, 0xb8, 0xfe,
|
||||
0x42, 0x3d, 0xfe, 0xc1, 0xb0, 0xba, 0xd3, 0xfe, 0xc1, 0xb0,
|
||||
0xb6, 0xfe, 0x3b, 0x3f, 0xe7, 0xba, 0xb8, 0xbc, 0xc5, 0xc1,
|
||||
0xc1, 0xcd, 0xfe, 0x3b, 0x37, 0xfe, 0xc1, 0xb4, 0xb6, 0xb8,
|
||||
0xb6, 0xb8, 0xc5, 0x5c, 0x3f, 0x46, 0xfe, 0xcd, 0xc5, 0xcd,
|
||||
0xcd, 0xc1, 0xb2, 0xb2, 0xfe, 0x3f, 0x35, 0x54, 0xdb, 0xc1,
|
||||
0xcd, 0xcd, 0xbc, 0xaf, 0xac, 0xb6, 0x54, 0x35, 0x31, 0x68,
|
||||
0xba, 0xb8, 0xcd, 0xdb, 0xc9, 0xb2, 0xb4, 0xc9, 0x46, 0x39,
|
||||
0x42, 0xdb, 0xbc, 0xbc, 0xcd, 0xcd, 0xbe, 0xb2, 0xb8, 0xe7,
|
||||
0x54, 0x46, 0xfe, 0xfe, 0xdb, 0xc9, 0xc5, 0xbe, 0xbe, 0xc9,
|
||||
0xfe, 0x5c, 0x5c, 0xfe, 0xd3, 0xcd, 0xcd, 0xc5, 0xb6, 0xb2,
|
||||
0xc5, 0x68, 0x4e, 0xfe, 0xc5, 0xc1, 0xcd, 0x68, 0x5c, 0xe7,
|
||||
0xb8, 0xb6, 0xd3, 0x4a, 0x46, 0xfe, 0xbc, 0xb8, 0xc1, 0xe7,
|
||||
0xe7, 0xc1, 0xb4, 0xbe, 0xfe, 0x3f, 0x3f, 0xfe, 0xba, 0xb2,
|
||||
0xba, 0xe7, 0xfe, 0xcd, 0xcd, 0xfe, 0x4e, 0x46, 0xfe, 0xc5,
|
||||
0xb8, 0xb2, 0xba, 0xc1, 0xcd, 0xd3, 0xe7, 0xfe, 0x5c, 0x5c,
|
||||
0xfe, 0xe7, 0xc5, 0xbe, 0xb6, 0xba, 0xc5, 0xfe, 0x3f, 0x3f,
|
||||
0x54, 0xfe, 0xd3, 0xc1, 0xbc, 0xb6, 0xb0, 0xb0, 0xd3, 0x54,
|
||||
0x39, 0x46, 0xfe, 0xc1, 0xcd, 0xe7, 0xe7, 0xc5, 0xb8, 0xb4,
|
||||
0xd3, 0x54, 0x37, 0x42, 0xdb, 0xbe, 0xc1, 0xd3, 0xcd, 0xb8,
|
||||
0xb0, 0xb0, 0xcd, 0x4a, 0x3b, 0x42, 0xe7, 0xc5, 0xbe, 0xcd,
|
||||
0xe7, 0xd3, 0xc5, 0xcd, 0xfe, 0x54, 0x54, 0x68, 0xe7, 0xc5,
|
||||
0xc1, 0xc1, 0xcd, 0xcd, 0xc9, 0xc9, 0xcd, 0xe7, 0xfe, 0xfe,
|
||||
0xfe, 0xe7, 0xc5, 0xbe, 0xc1, 0xfe, 0x5c, 0x5c, 0xfe, 0xcd,
|
||||
0xcd, 0xcd, 0xdb, 0xd3, 0xc1, 0xbc, 0xbe, 0xfe, 0x4e, 0x54,
|
||||
0xcd, 0xb6, 0xb8, 0xd3, 0x5c, 0x5c, 0xfe, 0xc5, 0xc9, 0xfe,
|
||||
0x46, 0x4a, 0xe7, 0xb4, 0xb6, 0xc5, 0xfe, 0xe7, 0xcd, 0xc9,
|
||||
0xdb, 0xfe, 0x4e, 0x68, 0xd3, 0xb6, 0xb2, 0xbc, 0xfe, 0x68,
|
||||
0xfe, 0xfe, 0x68, 0x54, 0x68, 0xe7, 0xc5, 0xbc, 0xb8, 0xbe,
|
||||
0xcd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xd3, 0xd3, 0xcd,
|
||||
0xc1, 0xb8, 0xbc, 0xdb, 0x4e, 0x42, 0x4a, 0xfe, 0xc9, 0xc1,
|
||||
0xcd, 0xd3, 0xcd, 0xba, 0xb8, 0xcd, 0x46, 0x3b, 0xfe, 0xc9,
|
||||
0xba, 0xcd, 0xe7, 0xfe, 0xd3, 0xc1, 0xba, 0xdb, 0x54, 0x3d,
|
||||
0x68, 0xd3, 0xbc, 0xcd, 0xfe, 0xfe, 0xc5, 0xbe, 0xc1, 0xe7,
|
||||
0x54, 0x4a, 0xfe, 0xc9, 0xc1, 0xcd, 0xfe, 0xfe, 0xd3, 0xd3,
|
||||
0xd3, 0xfe, 0xe7, 0xe7, 0xe7, 0xdb, 0xd3, 0xe7, 0xe7, 0xe7,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xcd, 0xc9, 0xdb, 0xfe, 0xfe, 0xdb,
|
||||
0xbe, 0xc9, 0xfe, 0x5c, 0xfe, 0xc9, 0xbc, 0xbe, 0xdb, 0x68,
|
||||
0x5c, 0xdb, 0xc5, 0xd3, 0x54, 0x46, 0xfe, 0xbc, 0xb2, 0xb8,
|
||||
0xdb, 0x68, 0x68, 0xe7, 0xcd, 0xdb, 0x5c, 0x54, 0xfe, 0xc1,
|
||||
0xb8, 0xc1, 0xe7, 0xfe, 0xfe, 0xe7, 0xe7, 0xfe, 0xfe, 0xfe,
|
||||
0xd3, 0xc5, 0xc1, 0xc5, 0xcd, 0xd3, 0xe7, 0xfe, 0x54, 0x4e,
|
||||
0xfe, 0xd3, 0xcd, 0xd3, 0xd3, 0xc5, 0xc1, 0xc1, 0xe7, 0x5c,
|
||||
0x4e, 0x5c, 0xd3, 0xc1, 0xcd, 0xfe, 0xfe, 0xcd, 0xba, 0xba,
|
||||
0xe7, 0x4a, 0x4a, 0x68, 0xcd, 0xc5, 0xcd, 0xfe, 0xfe, 0xcd,
|
||||
0xb8, 0xc1, 0xe7, 0x4e, 0x5c, 0xe7, 0xc1, 0xc9, 0xdb, 0xfe,
|
||||
0xe7, 0xc9, 0xc5, 0xd3, 0xfe, 0x68, 0xfe, 0xdb, 0xd3, 0xe7,
|
||||
0xfe, 0xfe, 0xcd, 0xc9, 0xcd, 0xd3, 0xd3, 0xd3, 0xcd, 0xe7,
|
||||
0xfe, 0xfe, 0xe7, 0xc5, 0xc5, 0xe7, 0x68, 0x68, 0xe7, 0xc1,
|
||||
0xc5, 0xfe, 0x5c, 0xfe, 0xd3, 0xc1, 0xd3, 0xfe, 0x68, 0xe7,
|
||||
0xc5, 0xb6, 0xc5, 0xe7, 0x68, 0xfe, 0xcd, 0xc5, 0xe7, 0xfe,
|
||||
0x54, 0xfe, 0xc9, 0xc5, 0xdb, 0xfe, 0xfe, 0xfe, 0xd3, 0xd3,
|
||||
0xfe, 0xfe, 0xfe, 0xcd, 0xc1, 0xc1, 0xc9, 0xd3, 0xd3, 0xe7,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xe7, 0xd3, 0xdb, 0xe7, 0xe7, 0xd3,
|
||||
0xcd, 0xd3, 0xfe, 0xfe, 0xfe, 0xcd, 0xc5, 0xd3, 0xe7, 0xe7,
|
||||
0xc9, 0xbc, 0xbe, 0xe7, 0x68, 0x4a, 0xfe, 0xdb, 0xcd, 0xfe,
|
||||
0xfe, 0xfe, 0xcd, 0xc1, 0xc9, 0xfe, 0x54, 0x5c, 0xe7, 0xc9,
|
||||
0xc5, 0xe7, 0xfe, 0xfe, 0xcd, 0xc5, 0xc5, 0xe7, 0xfe, 0xfe,
|
||||
0xfe, 0xe7, 0xe7, 0xfe, 0xfe, 0xdb, 0xd3, 0xd3, 0xdb, 0xe7,
|
||||
0xfe, 0xfe, 0xe7, 0xe7, 0xdb, 0xd3, 0xc9, 0xd3, 0xe7, 0xfe,
|
||||
0xfe, 0xd3, 0xd3, 0xdb, 0xfe, 0xfe, 0xfe, 0xd3, 0xcd, 0xcd,
|
||||
0xfe, 0xfe, 0xe7, 0xc9, 0xc5, 0xd3, 0xfe, 0xfe, 0xfe, 0xcd,
|
||||
0xc9, 0xd3, 0xfe, 0xfe, 0xfe, 0xdb, 0xc9, 0xcd, 0xe7, 0xfe,
|
||||
0xe7, 0xcd, 0xcd, 0xe7, 0xfe, 0xfe, 0xe7, 0xd3, 0xc5, 0xcd,
|
||||
0xe7, 0xfe, 0xfe, 0xfe, 0xdb, 0xe7, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xe7, 0xcd, 0xcd, 0xd3, 0xe7, 0xe7, 0xe7, 0xe7, 0xfe, 0xfe,
|
||||
0xe7, 0xe7, 0xdb, 0xc9, 0xc1, 0xc5, 0xfe, 0x5c, 0x68, 0xfe,
|
||||
0xd3, 0xdb, 0xe7, 0xe7, 0xe7, 0xd3, 0xc5, 0xcd, 0xe7, 0x68,
|
||||
0xfe, 0xe7, 0xcd, 0xd3, 0xe7, 0xfe, 0xe7, 0xcd, 0xc1, 0xc1,
|
||||
0xdb, 0xfe, 0x54, 0xfe, 0xe7, 0xcd, 0xe7, 0xfe, 0xe7, 0xd3,
|
||||
0xcd, 0xd3, 0xe7, 0xfe, 0xfe, 0xfe, 0xcd, 0xc5, 0xcd, 0xfe,
|
||||
0xfe, 0xe7, 0xcd, 0xd3, 0xdb, 0xe7, 0xfe, 0xfe, 0xfe, 0xe7,
|
||||
0xd3, 0xd3, 0xe7, 0xfe, 0xe7, 0xe7, 0xe7, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xdb, 0xc5, 0xc1, 0xd3, 0xfe, 0xfe, 0xfe, 0xd3, 0xc9,
|
||||
0xcd, 0xe7, 0xfe, 0xfe, 0xd3, 0xcd, 0xdb, 0xfe, 0x5c, 0xfe,
|
||||
0xcd, 0xc9, 0xd3, 0xfe, 0xfe, 0xfe, 0xd3, 0xc9, 0xcd, 0xfe,
|
||||
0x68, 0xfe, 0xd3, 0xc1, 0xc1, 0xdb, 0xfe, 0xfe, 0xe7, 0xe7,
|
||||
0xfe, 0xfe, 0x68, 0xfe, 0xe7, 0xc5, 0xc9, 0xdb, 0xfe, 0xfe,
|
||||
0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xdb, 0xc5, 0xc5,
|
||||
0xd3, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xe7, 0xe7, 0xfe, 0xfe,
|
||||
0xc9, 0xc1, 0xc5, 0xfe, 0x54, 0x5c, 0xfe, 0xcd, 0xc5, 0xcd,
|
||||
0xfe, 0xfe, 0xdb, 0xc5, 0xc9, 0xfe, 0x5c, 0x68, 0xfe, 0xcd,
|
||||
0xcd, 0xfe, 0xfe, 0xfe, 0xe7, 0xc5, 0xc1, 0xd3, 0xfe, 0xfe,
|
||||
0xdb, 0xc9, 0xc5, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xfe,
|
||||
0xfe, 0xfe, 0xe7, 0xcd, 0xcd, 0xdb, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xe7, 0xd3, 0xcd, 0xd3, 0xfe, 0xfe, 0xdb, 0xcd, 0xd3, 0xe7,
|
||||
0xfe, 0xfe, 0xfe, 0xdb, 0xcd, 0xd3, 0xe7, 0xfe, 0xd3, 0xc5,
|
||||
0xc9, 0xfe, 0x5c, 0x54, 0xfe, 0xcd, 0xc1, 0xcd, 0xe7, 0xfe,
|
||||
0xfe, 0xd3, 0xcd, 0xfe, 0x54, 0x5c, 0xe7, 0xc1, 0xc1, 0xd3,
|
||||
0xfe, 0xfe, 0xe7, 0xd3, 0xd3, 0xe7, 0xfe, 0xfe, 0xfe, 0xcd,
|
||||
0xc5, 0xcd, 0xd3, 0xe7, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xe7, 0xd3, 0xcd, 0xc9, 0xcd, 0xe7, 0xfe, 0xfe, 0xfe, 0xdb,
|
||||
0xc9, 0xcd, 0xe7, 0xfe, 0xe7, 0xc9, 0xc5, 0xdb, 0xfe, 0x5c,
|
||||
0xfe, 0xe7, 0xcd, 0xcd, 0xe7, 0xfe, 0xe7, 0xc5, 0xc1, 0xd3,
|
||||
0xfe, 0x5c, 0xfe, 0xcd, 0xc5, 0xcd, 0xe7, 0xfe, 0xfe, 0xe7,
|
||||
0xd3, 0xe7, 0xfe, 0xfe, 0xe7, 0xcd, 0xcd, 0xdb, 0xfe, 0xfe,
|
||||
0xfe, 0xe7, 0xe7, 0xe7, 0xe7, 0xfe, 0xe7, 0xdb, 0xcd, 0xd3,
|
||||
0xd3, 0xdb, 0xfe, 0xfe, 0xfe, 0xfe, 0xdb, 0xd3, 0xdb, 0xe7,
|
||||
0xe7, 0xdb, 0xd3, 0xe7, 0xfe, 0xfe, 0xfe, 0xe7, 0xc9, 0xc5,
|
||||
0xcd, 0xe7, 0xfe, 0xdb, 0xd3, 0xe7, 0xfe, 0x68, 0xfe, 0xe7,
|
||||
0xcd, 0xcd, 0xd3, 0xfe, 0xfe, 0xe7, 0xdb, 0xe7, 0xfe, 0x68,
|
||||
0xfe, 0xdb, 0xfe, 0x68, 0xbe, 0xb2, 0xae, 0xab, 0xb2, 0xfe,
|
||||
0x2f, 0x31, 0xdb, 0xac, 0xad, 0xaf, 0xab, 0xab, 0xb4, 0x68,
|
||||
0x37, 0x39, 0x3f, 0xe7, 0xb4, 0xa8, 0xaa, 0xb0, 0xbc, 0xbc,
|
||||
0xc5, 0x3f, 0x31, 0x3d, 0xfe, 0xc1, 0xb8, 0xb0, 0xa5, 0xa2,
|
||||
0xa8, 0xaf, 0xdb, 0x3b, 0x28, 0x2a, 0x3d, 0xbc, 0xb0, 0xaa,
|
||||
0xa2, 0x9f, 0xab, 0xfe, 0x29, 0x24, 0x29, 0x4a, 0xb4, 0xaa,
|
||||
0xa8, 0xa9, 0xa8, 0xa5, 0xac, 0xdb, 0x2c, 0x27, 0x35, 0x4a,
|
||||
0xfe, 0xcd, 0xb2, 0xa2, 0x9f, 0x9f, 0xae, 0x4e, 0x2c, 0x22,
|
||||
0x33, 0xfe, 0xba, 0xb0, 0xa6, 0x9f, 0xa3, 0xbc, 0x5c, 0x33,
|
||||
0x31, 0x39, 0x5c, 0xcd, 0xc1, 0xb4, 0xad, 0xaa, 0xad, 0xcd,
|
||||
0x54, 0x46, 0xfe, 0xe7, 0xfe, 0x54, 0xc5, 0xaf, 0xa6, 0xa9,
|
||||
0xb0, 0xfe, 0x3d, 0x39, 0x5c, 0xdb, 0xdb, 0xfe, 0xba, 0xac,
|
||||
0xa8, 0xc5, 0x39, 0x33, 0x54, 0xb8, 0xae, 0xad, 0xb8, 0xc1,
|
||||
0xcd, 0xbe, 0xbc, 0xfe, 0x39, 0x37, 0xfe, 0xb4, 0xba, 0xcd,
|
||||
0xdb, 0xb8, 0xb0, 0xb6, 0xfe, 0x4e, 0x39, 0x3d, 0xfe, 0xb0,
|
||||
0xaa, 0xa9, 0xa9, 0xaa, 0xb0, 0x5c, 0x29, 0x28, 0x31, 0xfe,
|
||||
0xba, 0xb4, 0xae, 0xab, 0xab, 0xb2, 0xfe, 0x3b, 0x2a, 0x2f,
|
||||
0x54, 0xb4, 0xb4, 0xba, 0xb2, 0xa3, 0x9f, 0xa8, 0xfe, 0x2c,
|
||||
0x27, 0x2a, 0x46, 0xfe, 0xc1, 0xbc, 0xb0, 0xa2, 0xa2, 0xb0,
|
||||
0x33, 0x22, 0x2b, 0x46, 0xc1, 0xb4, 0xb0, 0xab, 0xa8, 0xa8,
|
||||
0xb0, 0xdb, 0x42, 0x2c, 0x33, 0x4a, 0xfe, 0x5c, 0xdb, 0xb4,
|
||||
0xa8, 0xad, 0xba, 0xfe, 0x46, 0x39, 0x39, 0x4a, 0xfe, 0xbc,
|
||||
0xab, 0xa5, 0xa5, 0xb8, 0x68, 0x37, 0x4a, 0xe7, 0xfe, 0x4a,
|
||||
0x5c, 0xd3, 0xb0, 0xb2, 0xc1, 0x5c, 0x42, 0x46, 0xd3, 0xb4,
|
||||
0xbe, 0x54, 0x54, 0xb6, 0xab, 0xae, 0xe7, 0x46, 0x4a, 0xfe,
|
||||
0xcd, 0xc9, 0xd3, 0xe7, 0xe7, 0xbe, 0xb4, 0xc5, 0x37, 0x2c,
|
||||
0x37, 0xc1, 0xb0, 0xb2, 0xb4, 0xb2, 0xb6, 0xdb, 0x54, 0x4a,
|
||||
0x46, 0x42, 0x68, 0xba, 0xb2, 0xba, 0xc5, 0xb6, 0xb6, 0xcd,
|
||||
0x33, 0x2f, 0x39, 0x68, 0xfe, 0xe7, 0xba, 0xac, 0xa7, 0xa7,
|
||||
0xb2, 0xe7, 0x2d, 0x25, 0x2f, 0xd3, 0xbe, 0xd3, 0xc5, 0xac,
|
||||
0xa6, 0xac, 0xfe, 0x33, 0x2c, 0x2d, 0x54, 0xc1, 0xb4, 0xcd,
|
||||
0xcd, 0xaf, 0xa4, 0xa8, 0xe7, 0x31, 0x31, 0x39, 0x46, 0xfe,
|
||||
0xdb, 0xbc, 0xb6, 0xaf, 0xa9, 0xb2, 0xfe, 0x2f, 0xfe, 0xba,
|
||||
0xad, 0xba, 0x4e, 0x3d, 0x42, 0xfe, 0xc9, 0xc1, 0xe7, 0xfe,
|
||||
0xc1, 0xa9, 0xa6, 0xcd, 0x2a, 0x25, 0x3b, 0xbc, 0xb0, 0xb6,
|
||||
0xb8, 0xb4, 0xb4, 0xb8, 0xc1, 0xfe, 0x3d, 0x3d, 0xfe, 0xba,
|
||||
0xd3, 0x54, 0x54, 0xbe, 0xb0, 0xb4, 0xe7, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xc5, 0xb6, 0xa9, 0xaa, 0xba, 0x3d, 0x39,
|
||||
0xfe, 0xc1, 0xfe, 0x4a, 0x54, 0xbe, 0xb2, 0xb8, 0xfe, 0x3d,
|
||||
0x3b, 0xfe, 0xb0, 0xab, 0xc5, 0x39, 0x3b, 0xbc, 0xa7, 0xab,
|
||||
0xd3, 0x68, 0xfe, 0xd3, 0xcd, 0xfe, 0x54, 0x3d, 0xfe, 0xbc,
|
||||
0xac, 0xc9, 0x3f, 0x2e, 0xfe, 0xba, 0xb0, 0xba, 0xba, 0xb6,
|
||||
0xba, 0xd3, 0xfe, 0xfe, 0x5c, 0x54, 0xc9, 0xb4, 0xbe, 0x54,
|
||||
0x68, 0xcd, 0xb6, 0xfe, 0x46, 0x54, 0xcd, 0xc5, 0xdb, 0xfe,
|
||||
0xe7, 0xc1, 0xae, 0xa8, 0xac, 0xfe, 0x2e, 0x2e, 0xfe, 0xb6,
|
||||
0xc1, 0x5c, 0xe7, 0xb6, 0xaa, 0xb0, 0x54, 0x35, 0x2e, 0x4a,
|
||||
0xc1, 0xac, 0xbc, 0xfe, 0xfe, 0xaf, 0xa6, 0xac, 0xfe, 0x42,
|
||||
0x46, 0x5c, 0xfe, 0xfe, 0xfe, 0xe7, 0xc9, 0xae, 0xa9, 0xb0,
|
||||
0x54, 0x31, 0x37, 0xfe, 0xd3, 0xd3, 0xb8, 0xac, 0xab, 0xb6,
|
||||
0xe7, 0xfe, 0xfe, 0x68, 0xfe, 0xfe, 0xfe, 0x54, 0xfe, 0xb0,
|
||||
0xae, 0xb8, 0xfe, 0xe7, 0xc1, 0xb6, 0xe7, 0x46, 0x3d, 0xe7,
|
||||
0xae, 0xa7, 0xab, 0xdb, 0x3f, 0x37, 0xfe, 0xba, 0xcd, 0x3f,
|
||||
0x42, 0xc5, 0xab, 0xac, 0xc9, 0x46, 0x3d, 0x54, 0xba, 0xad,
|
||||
0xb0, 0xfe, 0x68, 0xcd, 0xb0, 0xb0, 0xc9, 0x54, 0x54, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xe7, 0xcd, 0xbe, 0xba, 0xc5, 0x68, 0x42,
|
||||
0x46, 0xe7, 0xc5, 0xba, 0xaf, 0xa7, 0xa7, 0xbc, 0xfe, 0x3d,
|
||||
0x4a, 0x68, 0xfe, 0xfe, 0xfe, 0xe7, 0xbc, 0xaf, 0xae, 0xc5,
|
||||
0x3d, 0x39, 0xfe, 0xbc, 0xbe, 0xfe, 0x68, 0xc9, 0xa9, 0xa2,
|
||||
0xaa, 0xbc, 0x3b, 0x2d, 0x35, 0xfe, 0xcd, 0xfe, 0xfe, 0xb4,
|
||||
0xa9, 0xa6, 0xbc, 0x54, 0x31, 0x31, 0x54, 0xd3, 0xbc, 0xc5,
|
||||
0xcd, 0xb8, 0xab, 0xa8, 0xb4, 0xfe, 0x54, 0x4e, 0x68, 0x54,
|
||||
0xfe, 0xc9, 0xba, 0xb4, 0xb4, 0xba, 0xcd, 0x5c, 0x3b, 0x3f,
|
||||
0x54, 0xfe, 0xcd, 0xaf, 0xa8, 0xac, 0xc5, 0x68, 0xfe, 0xe7,
|
||||
0xdb, 0xfe, 0xfe, 0xfe, 0xcd, 0xb8, 0xaf, 0xb6, 0xe7, 0x42,
|
||||
0x5c, 0xcd, 0xbc, 0xfe, 0x46, 0x68, 0xba, 0xb0, 0xab, 0xbc,
|
||||
0x54, 0x3d, 0x46, 0xc9, 0xb8, 0xbc, 0xdb, 0xd3, 0xb6, 0xb0,
|
||||
0xb6, 0x5c, 0x37, 0x35, 0x54, 0xc9, 0xba, 0xb4, 0xc1, 0xc9,
|
||||
0xc1, 0xba, 0xe7, 0x5c, 0x3d, 0x54, 0xfe, 0xcd, 0xc5, 0xb8,
|
||||
0xae, 0xaf, 0xb4, 0xd3, 0x54, 0x3b, 0x35, 0x46, 0xfe, 0xdb,
|
||||
0xbc, 0xaf, 0xa9, 0xab, 0xd3, 0x3f, 0x31, 0x3f, 0xfe, 0xe7,
|
||||
0xdb, 0xcd, 0xb8, 0xae, 0xaa, 0xac, 0xe7, 0x33, 0x2d, 0x3f,
|
||||
0xd3, 0xdb, 0xfe, 0xfe, 0xbc, 0xaa, 0xa9, 0xb0, 0xfe, 0x31,
|
||||
0x2f, 0x3d, 0xdb, 0xc5, 0xcd, 0xc9, 0xae, 0xa8, 0xad, 0xfe,
|
||||
0x46, 0x39, 0x46, 0x5c, 0xfe, 0xcd, 0xc5, 0xc1, 0xb6, 0xb0,
|
||||
0xbc, 0x68, 0x42, 0x4e, 0xe7, 0xfe, 0x5c, 0xfe, 0xb6, 0xaf,
|
||||
0xb0, 0xc5, 0xe7, 0x5c, 0x5c, 0xfe, 0xe7, 0xfe, 0x68, 0xe7,
|
||||
0xb0, 0xac, 0xb2, 0x4a, 0x35, 0x3f, 0xcd, 0xbc, 0xc1, 0xe7,
|
||||
0xe7, 0xd3, 0xb6, 0xb4, 0xfe, 0x3b, 0x33, 0xfe, 0xba, 0xb4,
|
||||
0xd3, 0xfe, 0xc9, 0xb4, 0xb4, 0xcd, 0x4a, 0x3b, 0x3b, 0xfe,
|
||||
0xb8, 0xb6, 0xc5, 0xc5, 0xb8, 0xb0, 0xcd, 0x4a, 0x31, 0x3b,
|
||||
0x68, 0xcd, 0xc1, 0xba, 0xb4, 0xb0, 0xb0, 0xba, 0x5c, 0x2f,
|
||||
0x2f, 0x4e, 0xc9, 0xc1, 0xdb, 0xc9, 0xb4 };
|
||||
207
apps/leave.h
Normal file
207
apps/leave.h
Normal file
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* U-law 8-bit audio data
|
||||
*
|
||||
* Source: leave.raw
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer and Linux Support Services
|
||||
*
|
||||
* Distributed under the terms of the GNU General Public License
|
||||
*
|
||||
*/
|
||||
|
||||
static unsigned char leave[] = {
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xc1, 0x3d,
|
||||
0x42, 0x46, 0x3f, 0x3f, 0x46, 0x3f, 0x4e, 0xba, 0xbe, 0xbe,
|
||||
0xbc, 0xba, 0xbe, 0xc5, 0xb6, 0x2e, 0x2c, 0x33, 0x2f, 0x2e,
|
||||
0x2f, 0x33, 0x2b, 0x54, 0xac, 0xb0, 0xb0, 0xad, 0xaf, 0xb0,
|
||||
0xae, 0xcd, 0x3b, 0x2f, 0x31, 0x2e, 0x2f, 0x31, 0x2e, 0x46,
|
||||
0xc5, 0xaf, 0xb0, 0xaf, 0xae, 0xaf, 0xaf, 0xb0, 0xfe, 0x2d,
|
||||
0x31, 0x31, 0x2e, 0x31, 0x2f, 0x31, 0xfe, 0xae, 0xaf, 0xaf,
|
||||
0xae, 0xb0, 0xae, 0xaf, 0xfe, 0xdb, 0x2e, 0x2e, 0x31, 0x31,
|
||||
0x2d, 0x2e, 0xdb, 0x68, 0xaf, 0xad, 0xb0, 0xb0, 0xae, 0xaf,
|
||||
0x5c, 0xe7, 0x39, 0x2d, 0x31, 0x31, 0x31, 0x2d, 0xfe, 0xfe,
|
||||
0x68, 0xad, 0xaf, 0xb0, 0xaf, 0xac, 0xbc, 0xfe, 0xd3, 0x2f,
|
||||
0x2e, 0x33, 0x31, 0x2d, 0x4e, 0xdb, 0xfe, 0xfe, 0xac, 0xaf,
|
||||
0xb0, 0xac, 0xb6, 0x68, 0xe7, 0xdb, 0x2e, 0x2f, 0x35, 0x2f,
|
||||
0x31, 0xe7, 0xe7, 0x68, 0xad, 0xac, 0xb0, 0xae, 0xac, 0xfe,
|
||||
0xfe, 0xdb, 0xfe, 0x2d, 0x33, 0x31, 0x2e, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xbc, 0xaf, 0xb0, 0xad, 0xfe, 0xfe, 0xfe, 0xe7, 0x5c,
|
||||
0x2e, 0x33, 0x2e, 0x35, 0xe7, 0xfe, 0xfe, 0xfe, 0xad, 0xb0,
|
||||
0xaf, 0xc1, 0xfe, 0xe7, 0xfe, 0xe7, 0x3d, 0x31, 0x2f, 0x37,
|
||||
0xe7, 0xfe, 0xfe, 0xe7, 0xfe, 0xaf, 0xad, 0xbe, 0xfe, 0xdb,
|
||||
0xfe, 0xfe, 0xdb, 0x35, 0x2d, 0x39, 0xdb, 0xfe, 0xfe, 0xdb,
|
||||
0xfe, 0xfe, 0xad, 0xaf, 0xfe, 0xfe, 0xe7, 0x68, 0xfe, 0xd3,
|
||||
0x2e, 0x2c, 0xdb, 0xdb, 0x2c, 0x35, 0xd3, 0x68, 0xaf, 0xad,
|
||||
0xb0, 0xb0, 0xad, 0xba, 0x68, 0xe7, 0xe7, 0x2e, 0x2f, 0x33,
|
||||
0x31, 0x2d, 0xdb, 0xd3, 0x5c, 0xae, 0xaa, 0xe7, 0x68, 0xaa,
|
||||
0xe7, 0xfe, 0xdb, 0xe7, 0xfe, 0xe7, 0xd3, 0x2d, 0xfe, 0xdb,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xc5, 0xfe, 0xe7, 0xe7,
|
||||
0xfe, 0xfe, 0xe7, 0xe7, 0x3b, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xe7, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xc5, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xe7, 0xfe, 0x3b,
|
||||
0xdb, 0xfe, 0xfe, 0xfe, 0xe7, 0xfe, 0xfe, 0xb0, 0xfe, 0xfe,
|
||||
0xe7, 0xfe, 0xfe, 0xfe, 0xdb, 0x2e, 0x5c, 0xdb, 0xfe, 0xfe,
|
||||
0xe7, 0xe7, 0x68, 0xb0, 0xbe, 0x68, 0xe7, 0xe7, 0xfe, 0xfe,
|
||||
0xdb, 0x39, 0x2f, 0xdb, 0xfe, 0xfe, 0xe7, 0xe7, 0xfe, 0xbe,
|
||||
0xaf, 0xe7, 0x68, 0xe7, 0xfe, 0xfe, 0xfe, 0xfe, 0x33, 0x33,
|
||||
0xdb, 0xfe, 0xfe, 0xdb, 0xe7, 0xfe, 0xb0, 0xb0, 0xfe, 0xfe,
|
||||
0xe7, 0xfe, 0xfe, 0xfe, 0x35, 0x33, 0xe7, 0xe7, 0xfe, 0xe7,
|
||||
0xe7, 0xfe, 0xb0, 0xb2, 0xb0, 0xfe, 0xfe, 0xe7, 0xfe, 0xe7,
|
||||
0x46, 0x35, 0x35, 0x3f, 0xe7, 0xfe, 0xe7, 0xfe, 0xb2, 0xb0,
|
||||
0xb2, 0xb0, 0xfe, 0xfe, 0xfe, 0xfe, 0x42, 0x35, 0x37, 0x33,
|
||||
0xe7, 0xfe, 0xfe, 0xfe, 0xb8, 0xb0, 0xb6, 0xb0, 0xba, 0xfe,
|
||||
0xfe, 0xe7, 0xe7, 0x33, 0x39, 0x39, 0x33, 0xe7, 0xdb, 0xfe,
|
||||
0xe7, 0xb0, 0xb4, 0xb6, 0xb0, 0xcd, 0xfe, 0xe7, 0xe7, 0x33,
|
||||
0x39, 0x3b, 0x33, 0x46, 0xd3, 0xfe, 0xfe, 0xb0, 0xb2, 0xb6,
|
||||
0xb4, 0xb0, 0xfe, 0xfe, 0xdb, 0x35, 0x37, 0x39, 0x39, 0x35,
|
||||
0x37, 0xdb, 0x68, 0xcd, 0xb2, 0xb6, 0xb6, 0xb4, 0xb4, 0x68,
|
||||
0xe7, 0x42, 0x37, 0x3b, 0x3b, 0x39, 0x37, 0xdb, 0xfe, 0xcd,
|
||||
0xb2, 0xb6, 0xb6, 0xb6, 0xb2, 0xb4, 0xfe, 0x54, 0x37, 0x3b,
|
||||
0x39, 0x3b, 0x3b, 0x39, 0xe7, 0xfe, 0xb6, 0xb6, 0xb6, 0xb4,
|
||||
0xb6, 0xb6, 0xbc, 0xfe, 0x3f, 0x3b, 0x3b, 0x39, 0x3b, 0x3b,
|
||||
0x39, 0xe7, 0xb6, 0xb8, 0xb8, 0xb6, 0xb8, 0xb8, 0xb4, 0xfe,
|
||||
0x3b, 0x3d, 0x3d, 0x3b, 0x39, 0x3d, 0x3b, 0x39, 0xbe, 0xb8,
|
||||
0xba, 0xb8, 0xb6, 0xb8, 0xba, 0xb4, 0xfe, 0x39, 0x3f, 0x3d,
|
||||
0x3b, 0x3d, 0x3f, 0x39, 0xdb, 0xb4, 0xba, 0xb8, 0xb6, 0xb8,
|
||||
0xbc, 0xb4, 0xba, 0x39, 0x42, 0x3f, 0x3d, 0x3d, 0x3f, 0x3f,
|
||||
0x3b, 0xb8, 0xb6, 0xbc, 0xb8, 0xb8, 0xba, 0xbc, 0xb8, 0xe7,
|
||||
0x3d, 0x42, 0x3f, 0x3d, 0x3f, 0x42, 0x3d, 0xfe, 0xb8, 0xbc,
|
||||
0xbc, 0xba, 0xba, 0xbc, 0xba, 0xe7, 0x3d, 0x3f, 0x42, 0x3f,
|
||||
0x3f, 0x42, 0x42, 0xfe, 0xfe, 0xbc, 0xbc, 0xbe, 0xbc, 0xbe,
|
||||
0xbc, 0xc5, 0xe7, 0x68, 0x42, 0x46, 0x42, 0x46, 0x42, 0x46,
|
||||
0xfe, 0xfe, 0xbc, 0xbe, 0xbe, 0xbe, 0xbc, 0xc5, 0xfe, 0xdb,
|
||||
0x46, 0x46, 0x4a, 0x4a, 0x46, 0x46, 0xe7, 0xfe, 0xd3, 0xbe,
|
||||
0xc9, 0xc9, 0xc5, 0xc5, 0xe7, 0xdb, 0xd3, 0x4a, 0x4e, 0x54,
|
||||
0x4e, 0x4e, 0xfe, 0x5c, 0x54, 0xd3, 0xcd, 0xd3, 0xd3, 0xcd,
|
||||
0xd3, 0xd3, 0xcd, 0xfe, 0x5c, 0x68, 0x5c, 0x5c, 0x5c, 0x68,
|
||||
0x5c, 0x5c, 0xcd, 0xcd, 0xd3, 0xcd, 0xdb, 0xe7, 0xe7, 0xdb,
|
||||
0xe7, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xe7,
|
||||
0xfe, 0x5c, 0x5c, 0xfe, 0xfe, 0xfe, 0xfe, 0x46, 0x35, 0x35,
|
||||
0x37, 0x39, 0x3b, 0x39, 0x35, 0x33, 0x35, 0x5c, 0xd3, 0xcd,
|
||||
0xdb, 0xfe, 0xfe, 0xd3, 0xb0, 0xb0, 0xb0, 0xb4, 0xb4, 0xb6,
|
||||
0xb2, 0xb0, 0xb0, 0xb6, 0xcd, 0x5c, 0x68, 0xfe, 0xfe, 0xfe,
|
||||
0x3b, 0x33, 0x35, 0x37, 0x39, 0x3b, 0x39, 0x37, 0x35, 0x35,
|
||||
0x3f, 0xdb, 0xcd, 0xcd, 0xdb, 0xfe, 0xe7, 0xc5, 0xb0, 0xb0,
|
||||
0xb2, 0xb6, 0xb6, 0xb6, 0xb2, 0xb0, 0xb0, 0xcd, 0x5c, 0x5c,
|
||||
0xfe, 0xe7, 0xe7, 0xfe, 0x35, 0x35, 0x35, 0x39, 0x3b, 0x3b,
|
||||
0x39, 0x35, 0x33, 0x39, 0xdb, 0xcd, 0xd3, 0xe7, 0xfe, 0xfe,
|
||||
0xba, 0xb0, 0xb0, 0xb2, 0xb4, 0xb6, 0xb6, 0xb4, 0xb2, 0xb0,
|
||||
0xb4, 0xc9, 0x5c, 0x68, 0xfe, 0xfe, 0x5c, 0x3b, 0x35, 0x37,
|
||||
0x39, 0x3b, 0x3b, 0x3b, 0x39, 0x37, 0x37, 0x3d, 0xe7, 0xcd,
|
||||
0xdb, 0xfe, 0xe7, 0xbe, 0xb2, 0xb2, 0xb4, 0xb4, 0xb6, 0xb6,
|
||||
0xb6, 0xb4, 0xb0, 0xb0, 0xc5, 0x5c, 0x5c, 0xfe, 0xe7, 0xe7,
|
||||
0x4e, 0x35, 0x35, 0x37, 0x3b, 0x3b, 0x3b, 0x39, 0x37, 0x37,
|
||||
0x3b, 0xe7, 0xc9, 0xcd, 0xe7, 0xfe, 0xd3, 0xb4, 0xb2, 0xb2,
|
||||
0xb4, 0xb6, 0xb6, 0xb6, 0xb6, 0xb4, 0xb2, 0xb4, 0xc1, 0x68,
|
||||
0x68, 0xfe, 0xfe, 0x42, 0x39, 0x37, 0x39, 0x3b, 0x3b, 0x3b,
|
||||
0x3b, 0x3b, 0x39, 0x37, 0x3b, 0xfe, 0xd3, 0xdb, 0xfe, 0xcd,
|
||||
0xb4, 0xb2, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb6, 0xb4, 0xb2,
|
||||
0xb2, 0xc1, 0x5c, 0x5c, 0xfe, 0xfe, 0xfe, 0x3d, 0x37, 0x37,
|
||||
0x39, 0x3b, 0x3b, 0x3b, 0x3b, 0x37, 0x37, 0x39, 0xfe, 0xcd,
|
||||
0xd3, 0xfe, 0xfe, 0xc1, 0xb2, 0xb2, 0xb4, 0xb6, 0xb6, 0xb6,
|
||||
0xb6, 0xb6, 0xb6, 0xb4, 0xb4, 0xbc, 0x68, 0xfe, 0xfe, 0xfe,
|
||||
0x3b, 0x39, 0x39, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x39,
|
||||
0x39, 0x3b, 0xfe, 0xdb, 0xe7, 0xfe, 0xbc, 0xb6, 0xb6, 0xb6,
|
||||
0xb8, 0xb6, 0xb6, 0xb6, 0xb8, 0xb6, 0xb4, 0xb4, 0xbc, 0xfe,
|
||||
0x68, 0xfe, 0xe7, 0x5c, 0x3b, 0x39, 0x39, 0x3b, 0x3b, 0x3b,
|
||||
0x3d, 0x3d, 0x3b, 0x39, 0x3b, 0x68, 0xdb, 0xdb, 0xfe, 0xe7,
|
||||
0xb8, 0xb6, 0xb6, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb6,
|
||||
0xb4, 0xb6, 0xdb, 0x68, 0xfe, 0xfe, 0x46, 0x3b, 0x3b, 0x3b,
|
||||
0x3d, 0x3d, 0x3b, 0x3d, 0x3d, 0x3d, 0x3d, 0x3b, 0x3b, 0x5c,
|
||||
0xdb, 0xdb, 0xc9, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8,
|
||||
0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xbc, 0xcd, 0xfe, 0xfe, 0x3d,
|
||||
0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3b, 0x3d, 0x3d, 0x3d, 0x3d,
|
||||
0x3b, 0x3d, 0x46, 0xfe, 0xe7, 0xe7, 0xc5, 0xb8, 0xb8, 0xb8,
|
||||
0xba, 0xba, 0xb8, 0xb8, 0xba, 0xba, 0xb8, 0xb8, 0xb8, 0xcd,
|
||||
0xfe, 0xfe, 0x68, 0x3f, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d,
|
||||
0x3d, 0x3d, 0x3f, 0x3f, 0x3d, 0x3b, 0x4a, 0xfe, 0xdb, 0xbc,
|
||||
0xb8, 0xba, 0xba, 0xba, 0xba, 0xb8, 0xb8, 0xb8, 0xba, 0xba,
|
||||
0xba, 0xba, 0xba, 0xc5, 0xfe, 0x54, 0x3f, 0x3f, 0x3f, 0x3f,
|
||||
0x3f, 0x3f, 0x3d, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x42,
|
||||
0xfe, 0xe7, 0xdb, 0xbc, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
|
||||
0xba, 0xba, 0xbc, 0xba, 0xba, 0xba, 0xc5, 0xfe, 0xfe, 0x4e,
|
||||
0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x42,
|
||||
0x42, 0x42, 0x3f, 0x46, 0xfe, 0xcd, 0xb8, 0xba, 0xbc, 0xbc,
|
||||
0xbc, 0xba, 0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xba, 0xb8,
|
||||
0xbe, 0xfe, 0x42, 0x3d, 0x3f, 0x42, 0x42, 0x42, 0x3f, 0x3f,
|
||||
0x3f, 0x42, 0x42, 0x42, 0x42, 0x3f, 0x3f, 0x68, 0xdb, 0xc5,
|
||||
0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xba, 0xba, 0xba, 0xbc, 0xbc,
|
||||
0xbc, 0xbc, 0xba, 0xc1, 0xfe, 0xfe, 0x3f, 0x42, 0x46, 0x46,
|
||||
0x46, 0x42, 0x42, 0x42, 0x42, 0x42, 0x46, 0x46, 0x42, 0x3f,
|
||||
0x42, 0x68, 0xbe, 0xba, 0xbc, 0xbe, 0xbe, 0xbe, 0xbc, 0xbc,
|
||||
0xbc, 0xbc, 0xbe, 0xc1, 0xbe, 0xbc, 0xba, 0xbe, 0x68, 0x3f,
|
||||
0x42, 0x46, 0x4a, 0x4a, 0x46, 0x42, 0x42, 0x42, 0x46, 0x46,
|
||||
0x46, 0x46, 0x42, 0x42, 0x68, 0xd3, 0xbc, 0xbc, 0xbe, 0xc1,
|
||||
0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xc1, 0xc1, 0xbe, 0xbe,
|
||||
0xc1, 0xfe, 0x4e, 0x42, 0x46, 0x4a, 0x4a, 0x4a, 0x46, 0x46,
|
||||
0x46, 0x46, 0x4a, 0x4a, 0x4a, 0x46, 0x46, 0x68, 0xdb, 0xbe,
|
||||
0xbe, 0xc1, 0xc5, 0xc1, 0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xc1,
|
||||
0xc5, 0xc5, 0xbe, 0xbc, 0xc1, 0x4e, 0x46, 0x46, 0x4a, 0x4e,
|
||||
0x4e, 0x4a, 0x46, 0x46, 0x46, 0x4a, 0x4a, 0x4e, 0x4a, 0x46,
|
||||
0x46, 0xfe, 0xbe, 0xbe, 0xc1, 0xc9, 0xc5, 0xc5, 0xc1, 0xc1,
|
||||
0xc1, 0xc1, 0xc5, 0xc5, 0xc5, 0xc5, 0xbe, 0xc1, 0xfe, 0x4a,
|
||||
0x4a, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4a, 0x4a, 0x4a, 0x4e,
|
||||
0x54, 0x4e, 0x4a, 0x4a, 0x4e, 0xcd, 0xc1, 0xc5, 0xc5, 0xc9,
|
||||
0xc5, 0xc5, 0xc5, 0xc5, 0xc9, 0xcd, 0xcd, 0xcd, 0xcd, 0xc9,
|
||||
0xc9, 0xd3, 0x68, 0x54, 0x5c, 0x68, 0x68, 0x68, 0x5c, 0x5c,
|
||||
0x5c, 0x5c, 0x5c, 0x68, 0x68, 0x5c, 0x54, 0x5c, 0xdb, 0xcd,
|
||||
0xcd, 0xdb, 0xdb, 0xdb, 0xdb, 0xd3, 0xd3, 0xe7, 0xe7, 0xe7,
|
||||
0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xe7, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe };
|
||||
@@ -1,161 +1,831 @@
|
||||
# Here's the doxygen configuration file for the asterisk source
|
||||
# code
|
||||
# Doxyfile 1.2.10
|
||||
|
||||
# This file describes the settings to be used by the documentation system
|
||||
# doxygen (www.doxygen.org) for a project
|
||||
#
|
||||
# All text after a hash (#) is considered a comment and will be ignored
|
||||
# The format is:
|
||||
# TAG = value [value, ...]
|
||||
# For lists items can also be appended using:
|
||||
# TAG += value [value, ...]
|
||||
# Values that contain spaces should be placed between quotes (" ")
|
||||
|
||||
|
||||
# Doxygen configuration generated by Doxywizard version 0.1
|
||||
#---------------------------------------------------------------------------
|
||||
# General configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
|
||||
# by quotes) that should identify the project.
|
||||
|
||||
PROJECT_NAME = Asterisk
|
||||
PROJECT_NUMBER = 0.1.8
|
||||
OUTPUT_DIRECTORY = doc/
|
||||
|
||||
# The PROJECT_NUMBER tag can be used to enter a project or revision number.
|
||||
# This could be handy for archiving the generated documentation or
|
||||
# if some version control system is used.
|
||||
|
||||
PROJECT_NUMBER = CVS
|
||||
|
||||
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
|
||||
# base path where the generated documentation will be put.
|
||||
# If a relative path is entered, it will be relative to the location
|
||||
# where doxygen was started. If left blank the current directory will be used.
|
||||
|
||||
OUTPUT_DIRECTORY = doc/api
|
||||
|
||||
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
|
||||
# documentation generated by doxygen is written. Doxygen will use this
|
||||
# information to generate all constant output in the proper language.
|
||||
# The default language is English, other supported languages are:
|
||||
# Brazilian, Chinese, Croatian, Czech, Danish, Dutch, Finnish, French,
|
||||
# German, Hungarian, Italian, Japanese, Korean, Norwegian, Polish,
|
||||
# Portuguese, Romanian, Russian, Slovak, Slovene, Spanish and Swedish.
|
||||
|
||||
OUTPUT_LANGUAGE = English
|
||||
|
||||
# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
|
||||
# documentation are documented, even if no documentation was available.
|
||||
# Private class members and static file members will be hidden unless
|
||||
# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
|
||||
|
||||
EXTRACT_ALL = YES
|
||||
|
||||
# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
|
||||
# will be included in the documentation.
|
||||
|
||||
EXTRACT_PRIVATE = NO
|
||||
|
||||
# If the EXTRACT_STATIC tag is set to YES all static members of a file
|
||||
# will be included in the documentation.
|
||||
|
||||
EXTRACT_STATIC = NO
|
||||
HIDE_UNDOC_MEMBERS = YES
|
||||
|
||||
# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
|
||||
# undocumented members of documented classes, files or namespaces.
|
||||
# If set to NO (the default) these members will be included in the
|
||||
# various overviews, but no documentation section is generated.
|
||||
# This option has no effect if EXTRACT_ALL is enabled.
|
||||
|
||||
HIDE_UNDOC_MEMBERS = NO
|
||||
|
||||
# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
|
||||
# undocumented classes that are normally visible in the class hierarchy.
|
||||
# If set to NO (the default) these class will be included in the various
|
||||
# overviews. This option has no effect if EXTRACT_ALL is enabled.
|
||||
|
||||
HIDE_UNDOC_CLASSES = NO
|
||||
|
||||
# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
|
||||
# include brief member descriptions after the members that are listed in
|
||||
# the file and class documentation (similar to JavaDoc).
|
||||
# Set to NO to disable this.
|
||||
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
|
||||
# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
|
||||
# the brief description of a member or function before the detailed description.
|
||||
# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
|
||||
# brief descriptions will be completely suppressed.
|
||||
|
||||
REPEAT_BRIEF = YES
|
||||
|
||||
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
|
||||
# Doxygen will generate a detailed section even if there is only a brief
|
||||
# description.
|
||||
|
||||
ALWAYS_DETAILED_SEC = NO
|
||||
|
||||
# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
|
||||
# path before files name in the file list and in the header files. If set
|
||||
# to NO the shortest path that makes the file name unique will be used.
|
||||
|
||||
FULL_PATH_NAMES = NO
|
||||
|
||||
# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
|
||||
# can be used to strip a user defined part of the path. Stripping is
|
||||
# only done if one of the specified strings matches the left-hand part of
|
||||
# the path. It is allowed to use relative paths in the argument list.
|
||||
|
||||
STRIP_FROM_PATH =
|
||||
|
||||
# The INTERNAL_DOCS tag determines if documentation
|
||||
# that is typed after a \internal command is included. If the tag is set
|
||||
# to NO (the default) then the documentation will be excluded.
|
||||
# Set it to YES to include the internal documentation.
|
||||
|
||||
INTERNAL_DOCS = NO
|
||||
CLASS_DIAGRAMS = YES
|
||||
|
||||
# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
|
||||
# generate a class diagram (in Html and LaTeX) for classes with base or
|
||||
# super classes. Setting the tag to NO turns the diagrams off.
|
||||
|
||||
CLASS_DIAGRAMS = NO
|
||||
|
||||
# If the SOURCE_BROWSER tag is set to YES then a list of source files will
|
||||
# be generated. Documented entities will be cross-referenced with these sources.
|
||||
|
||||
SOURCE_BROWSER = YES
|
||||
INLINE_SOURCES = NO
|
||||
|
||||
# Setting the INLINE_SOURCES tag to YES will include the body
|
||||
# of functions and classes directly in the documentation.
|
||||
|
||||
INLINE_SOURCES = YES
|
||||
|
||||
# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
|
||||
# doxygen to hide any special comment blocks from generated source code
|
||||
# fragments. Normal C and C++ comments will always remain visible.
|
||||
|
||||
STRIP_CODE_COMMENTS = NO
|
||||
|
||||
# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
|
||||
# file names in lower case letters. If set to YES upper case letters are also
|
||||
# allowed. This is useful if you have classes or files whose names only differ
|
||||
# in case and if your file system supports case sensitive file names. Windows
|
||||
# users are adviced to set this option to NO.
|
||||
|
||||
CASE_SENSE_NAMES = YES
|
||||
HIDE_SCOPE_NAMES = NO
|
||||
|
||||
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
|
||||
# (but less readable) file names. This can be useful is your file systems
|
||||
# doesn't support long names like on DOS, Mac, or CD-ROM.
|
||||
|
||||
SHORT_NAMES = NO
|
||||
|
||||
# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
|
||||
# will show members with their full class and namespace scopes in the
|
||||
# documentation. If set to YES the scope will be hidden.
|
||||
|
||||
HIDE_SCOPE_NAMES = YES
|
||||
|
||||
# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
|
||||
# will generate a verbatim copy of the header file for each class for
|
||||
# which an include is specified. Set to NO to disable this.
|
||||
|
||||
VERBATIM_HEADERS = YES
|
||||
|
||||
# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
|
||||
# will put list of the files that are included by a file in the documentation
|
||||
# of that file.
|
||||
|
||||
SHOW_INCLUDE_FILES = YES
|
||||
|
||||
# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
|
||||
# will interpret the first line (until the first dot) of a JavaDoc-style
|
||||
# comment as the brief description. If set to NO, the JavaDoc
|
||||
# comments will behave just like the Qt-style comments (thus requiring an
|
||||
# explict @brief command for a brief description.
|
||||
|
||||
JAVADOC_AUTOBRIEF = NO
|
||||
|
||||
# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
|
||||
# member inherits the documentation from any documented member that it
|
||||
# reimplements.
|
||||
|
||||
INHERIT_DOCS = YES
|
||||
|
||||
# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
|
||||
# is inserted in the documentation for inline members.
|
||||
|
||||
INLINE_INFO = YES
|
||||
|
||||
# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
|
||||
# will sort the (detailed) documentation of file and class members
|
||||
# alphabetically by member name. If set to NO the members will appear in
|
||||
# declaration order.
|
||||
|
||||
SORT_MEMBER_DOCS = YES
|
||||
DISTRIBUTE_GROUP_DOC = YES
|
||||
TAB_SIZE = 4
|
||||
ENABLED_SECTIONS =
|
||||
|
||||
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
|
||||
# tag is set to YES, then doxygen will reuse the documentation of the first
|
||||
# member in the group (if any) for the other members of the group. By default
|
||||
# all members of a group must be documented explicitly.
|
||||
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
|
||||
# The TAB_SIZE tag can be used to set the number of spaces in a tab.
|
||||
# Doxygen uses this value to replace tabs by spaces in code fragments.
|
||||
|
||||
TAB_SIZE = 3
|
||||
|
||||
# The GENERATE_TODOLIST tag can be used to enable (YES) or
|
||||
# disable (NO) the todo list. This list is created by putting \todo
|
||||
# commands in the documentation.
|
||||
|
||||
GENERATE_TODOLIST = YES
|
||||
|
||||
# The GENERATE_TESTLIST tag can be used to enable (YES) or
|
||||
# disable (NO) the test list. This list is created by putting \test
|
||||
# commands in the documentation.
|
||||
|
||||
GENERATE_TESTLIST = YES
|
||||
GENERATE_BUGLIST = NO
|
||||
|
||||
# The GENERATE_BUGLIST tag can be used to enable (YES) or
|
||||
# disable (NO) the bug list. This list is created by putting \bug
|
||||
# commands in the documentation.
|
||||
|
||||
GENERATE_BUGLIST = YES
|
||||
|
||||
# This tag can be used to specify a number of aliases that acts
|
||||
# as commands in the documentation. An alias has the form "name=value".
|
||||
# For example adding "sideeffect=\par Side Effects:\n" will allow you to
|
||||
# put the command \sideeffect (or @sideeffect) in the documentation, which
|
||||
# will result in a user defined paragraph with heading "Side Effects:".
|
||||
# You can put \n's in the value part of an alias to insert newlines.
|
||||
|
||||
ALIASES =
|
||||
MAX_INITIALIZER_LINES = 30
|
||||
OPTIMIZE_OUTPUT_FOR_C = NO
|
||||
|
||||
# The ENABLED_SECTIONS tag can be used to enable conditional
|
||||
# documentation sections, marked by \if sectionname ... \endif.
|
||||
|
||||
ENABLED_SECTIONS =
|
||||
|
||||
# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
|
||||
# the initial value of a variable or define consist of for it to appear in
|
||||
# the documentation. If the initializer consists of more lines than specified
|
||||
# here it will be hidden. Use a value of 0 to hide initializers completely.
|
||||
# The appearance of the initializer of individual variables and defines in the
|
||||
# documentation can be controlled using \showinitializer or \hideinitializer
|
||||
# command in the documentation regardless of this setting.
|
||||
|
||||
MAX_INITIALIZER_LINES = 5
|
||||
|
||||
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
|
||||
# only. Doxygen will then generate output that is more tailored for C.
|
||||
# For instance some of the names that are used will be different. The list
|
||||
# of all members will be omitted, etc.
|
||||
|
||||
OPTIMIZE_OUTPUT_FOR_C = YES
|
||||
|
||||
# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
|
||||
# at the bottom of the documentation of classes and structs. If set to YES the
|
||||
# list will mention the files that were used to generate the documentation.
|
||||
|
||||
SHOW_USED_FILES = YES
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to warning and progress messages
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# The QUIET tag can be used to turn on/off the messages that are generated
|
||||
# by doxygen. Possible values are YES and NO. If left blank NO is used.
|
||||
|
||||
QUIET = NO
|
||||
|
||||
# The WARNINGS tag can be used to turn on/off the warning messages that are
|
||||
# generated by doxygen. Possible values are YES and NO. If left blank
|
||||
# NO is used.
|
||||
|
||||
WARNINGS = YES
|
||||
|
||||
# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
|
||||
# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
|
||||
# automatically be disabled.
|
||||
|
||||
WARN_IF_UNDOCUMENTED = YES
|
||||
WARN_FORMAT = "$file:$line: $text"
|
||||
|
||||
# The WARN_FORMAT tag determines the format of the warning messages that
|
||||
# doxygen can produce. The string should contain the $file, $line, and $text
|
||||
# tags, which will be replaced by the file and line number from which the
|
||||
# warning originated and the warning text.
|
||||
|
||||
WARN_FORMAT =
|
||||
|
||||
# The WARN_LOGFILE tag can be used to specify a file to which warning
|
||||
# and error messages should be written. If left blank the output is written
|
||||
# to stderr.
|
||||
|
||||
WARN_LOGFILE =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
INPUT = .
|
||||
FILE_PATTERNS = *.h \
|
||||
*.c
|
||||
RECURSIVE = YES
|
||||
|
||||
# The INPUT tag can be used to specify the files and/or directories that contain
|
||||
# documented source files. You may enter file names like "myfile.cpp" or
|
||||
# directories like "/usr/src/myproject". Separate the files or directories
|
||||
# with spaces.
|
||||
|
||||
INPUT = ./ include/asterisk
|
||||
|
||||
# If the value of the INPUT tag contains directories, you can use the
|
||||
# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
|
||||
# and *.h) to filter out the source-files in the directories. If left
|
||||
# blank all files are included.
|
||||
|
||||
FILE_PATTERNS = *.c *.h
|
||||
|
||||
# The RECURSIVE tag can be used to turn specify whether or not subdirectories
|
||||
# should be searched for input files as well. Possible values are YES and NO.
|
||||
# If left blank NO is used.
|
||||
|
||||
RECURSIVE = NO
|
||||
|
||||
# The EXCLUDE tag can be used to specify files and/or directories that should
|
||||
# excluded from the INPUT source files. This way you can easily exclude a
|
||||
# subdirectory from a directory tree whose root is specified with the INPUT tag.
|
||||
|
||||
EXCLUDE =
|
||||
|
||||
# If the value of the INPUT tag contains directories, you can use the
|
||||
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
|
||||
# certain files from those directories.
|
||||
|
||||
EXCLUDE_PATTERNS =
|
||||
|
||||
# The EXAMPLE_PATH tag can be used to specify one or more files or
|
||||
# directories that contain example code fragments that are included (see
|
||||
# the \include command).
|
||||
|
||||
EXAMPLE_PATH =
|
||||
|
||||
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
|
||||
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
|
||||
# and *.h) to filter out the source-files in the directories. If left
|
||||
# blank all files are included.
|
||||
|
||||
EXAMPLE_PATTERNS =
|
||||
|
||||
# The IMAGE_PATH tag can be used to specify one or more files or
|
||||
# directories that contain image that are included in the documentation (see
|
||||
# the \image command).
|
||||
|
||||
IMAGE_PATH =
|
||||
|
||||
# The INPUT_FILTER tag can be used to specify a program that doxygen should
|
||||
# invoke to filter for each input file. Doxygen will invoke the filter program
|
||||
# by executing (via popen()) the command <filter> <input-file>, where <filter>
|
||||
# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
|
||||
# input file. Doxygen will then use the output that the filter program writes
|
||||
# to standard output.
|
||||
|
||||
INPUT_FILTER =
|
||||
|
||||
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
|
||||
# INPUT_FILTER) will be used to filter the input files when producing source
|
||||
# files to browse.
|
||||
|
||||
FILTER_SOURCE_FILES = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
ALPHABETICAL_INDEX = NO
|
||||
|
||||
# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
|
||||
# of all compounds will be generated. Enable this if the project
|
||||
# contains a lot of classes, structs, unions or interfaces.
|
||||
|
||||
ALPHABETICAL_INDEX = YES
|
||||
|
||||
# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
|
||||
# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
|
||||
# in which this list will be split (can be a number in the range [1..20])
|
||||
|
||||
COLS_IN_ALPHA_INDEX = 5
|
||||
|
||||
# In case all classes in a project start with a common prefix, all
|
||||
# classes will be put under the same header in the alphabetical index.
|
||||
# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
|
||||
# should be ignored while generating the index headers.
|
||||
|
||||
IGNORE_PREFIX =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the HTML output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
|
||||
# generate HTML output.
|
||||
|
||||
GENERATE_HTML = YES
|
||||
HTML_OUTPUT = html
|
||||
|
||||
# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
|
||||
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
|
||||
# put in front of it. If left blank `html' will be used as the default path.
|
||||
|
||||
HTML_OUTPUT =
|
||||
|
||||
# The HTML_HEADER tag can be used to specify a personal HTML header for
|
||||
# each generated HTML page. If it is left blank doxygen will generate a
|
||||
# standard header.
|
||||
|
||||
HTML_HEADER =
|
||||
|
||||
# The HTML_FOOTER tag can be used to specify a personal HTML footer for
|
||||
# each generated HTML page. If it is left blank doxygen will generate a
|
||||
# standard footer.
|
||||
|
||||
HTML_FOOTER =
|
||||
|
||||
# The HTML_STYLESHEET tag can be used to specify a user defined cascading
|
||||
# style sheet that is used by each HTML page. It can be used to
|
||||
# fine-tune the look of the HTML output. If the tag is left blank doxygen
|
||||
# will generate a default style sheet
|
||||
|
||||
HTML_STYLESHEET =
|
||||
|
||||
# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
|
||||
# files or namespaces will be aligned in HTML using tables. If set to
|
||||
# NO a bullet list will be used.
|
||||
|
||||
HTML_ALIGN_MEMBERS = YES
|
||||
|
||||
# If the GENERATE_HTMLHELP tag is set to YES, additional index files
|
||||
# will be generated that can be used as input for tools like the
|
||||
# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
|
||||
# of the generated HTML documentation.
|
||||
|
||||
GENERATE_HTMLHELP = NO
|
||||
|
||||
# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
|
||||
# controls if a separate .chi index file is generated (YES) or that
|
||||
# it should be included in the master .chm file (NO).
|
||||
|
||||
GENERATE_CHI = NO
|
||||
|
||||
# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
|
||||
# controls whether a binary table of contents is generated (YES) or a
|
||||
# normal table of contents (NO) in the .chm file.
|
||||
|
||||
BINARY_TOC = NO
|
||||
|
||||
# The TOC_EXPAND flag can be set to YES to add extra items for group members
|
||||
# to the contents of the Html help documentation and to the tree view.
|
||||
|
||||
TOC_EXPAND = NO
|
||||
|
||||
# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
|
||||
# top of each HTML page. The value NO (the default) enables the index and
|
||||
# the value YES disables it.
|
||||
|
||||
DISABLE_INDEX = NO
|
||||
|
||||
# This tag can be used to set the number of enum values (range [1..20])
|
||||
# that doxygen will group on one line in the generated HTML documentation.
|
||||
|
||||
ENUM_VALUES_PER_LINE = 4
|
||||
|
||||
# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
|
||||
# generated containing a tree-like index structure (just like the one that
|
||||
# is generated for HTML Help). For this to work a browser that supports
|
||||
# JavaScript and frames is required (for instance Netscape 4.0+
|
||||
# or Internet explorer 4.0+).
|
||||
|
||||
GENERATE_TREEVIEW = NO
|
||||
|
||||
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
|
||||
# used to set the initial width (in pixels) of the frame in which the tree
|
||||
# is shown.
|
||||
|
||||
TREEVIEW_WIDTH = 250
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the LaTeX output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_LATEX = YES
|
||||
LATEX_OUTPUT = ps
|
||||
|
||||
# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
|
||||
# generate Latex output.
|
||||
|
||||
GENERATE_LATEX = NO
|
||||
|
||||
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
|
||||
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
|
||||
# put in front of it. If left blank `latex' will be used as the default path.
|
||||
|
||||
LATEX_OUTPUT =
|
||||
|
||||
# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
|
||||
# LaTeX documents. This may be useful for small projects and may help to
|
||||
# save some trees in general.
|
||||
|
||||
COMPACT_LATEX = NO
|
||||
PAPER_TYPE = a4
|
||||
|
||||
# The PAPER_TYPE tag can be used to set the paper type that is used
|
||||
# by the printer. Possible values are: a4, a4wide, letter, legal and
|
||||
# executive. If left blank a4wide will be used.
|
||||
|
||||
PAPER_TYPE = a4wide
|
||||
|
||||
# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
|
||||
# packages that should be included in the LaTeX output.
|
||||
|
||||
EXTRA_PACKAGES =
|
||||
|
||||
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
|
||||
# the generated latex document. The header should contain everything until
|
||||
# the first chapter. If it is left blank doxygen will generate a
|
||||
# standard header. Notice: only use this tag if you know what you are doing!
|
||||
|
||||
LATEX_HEADER =
|
||||
PDF_HYPERLINKS = YES
|
||||
USE_PDFLATEX = YES
|
||||
|
||||
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
|
||||
# is prepared for conversion to pdf (using ps2pdf). The pdf file will
|
||||
# contain links (just like the HTML output) instead of page references
|
||||
# This makes the output suitable for online browsing using a pdf viewer.
|
||||
|
||||
PDF_HYPERLINKS = NO
|
||||
|
||||
# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
|
||||
# plain latex in the generated Makefile. Set this option to YES to get a
|
||||
# higher quality PDF documentation.
|
||||
|
||||
USE_PDFLATEX = NO
|
||||
|
||||
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
|
||||
# command to the generated LaTeX files. This will instruct LaTeX to keep
|
||||
# running if errors occur, instead of asking the user for help.
|
||||
# This option is also used when generating formulas in HTML.
|
||||
|
||||
LATEX_BATCHMODE = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the RTF output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_RTF = YES
|
||||
RTF_OUTPUT = rtf
|
||||
|
||||
# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
|
||||
# The RTF output is optimised for Word 97 and may not look very pretty with
|
||||
# other RTF readers or editors.
|
||||
|
||||
GENERATE_RTF = NO
|
||||
|
||||
# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
|
||||
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
|
||||
# put in front of it. If left blank `rtf' will be used as the default path.
|
||||
|
||||
RTF_OUTPUT =
|
||||
|
||||
# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
|
||||
# RTF documents. This may be useful for small projects and may help to
|
||||
# save some trees in general.
|
||||
|
||||
COMPACT_RTF = NO
|
||||
|
||||
# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
|
||||
# will contain hyperlink fields. The RTF file will
|
||||
# contain links (just like the HTML output) instead of page references.
|
||||
# This makes the output suitable for online browsing using WORD or other
|
||||
# programs which support those fields.
|
||||
# Note: wordpad (write) and others do not support links.
|
||||
|
||||
RTF_HYPERLINKS = NO
|
||||
|
||||
# Load stylesheet definitions from file. Syntax is similar to doxygen's
|
||||
# config file, i.e. a series of assigments. You only have to provide
|
||||
# replacements, missing definitions are set to their default value.
|
||||
|
||||
RTF_STYLESHEET_FILE =
|
||||
|
||||
# Set optional variables used in the generation of an rtf document.
|
||||
# Syntax is similar to doxygen's config file.
|
||||
|
||||
RTF_EXTENSIONS_FILE =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
|
||||
# generate man pages
|
||||
|
||||
GENERATE_MAN = NO
|
||||
MAN_OUTPUT = man
|
||||
MAN_EXTENSION = .3
|
||||
|
||||
# The MAN_OUTPUT tag is used to specify where the man pages will be put.
|
||||
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
|
||||
# put in front of it. If left blank `man' will be used as the default path.
|
||||
|
||||
MAN_OUTPUT =
|
||||
|
||||
# The MAN_EXTENSION tag determines the extension that is added to
|
||||
# the generated man pages (default is the subroutine's section .3)
|
||||
|
||||
MAN_EXTENSION =
|
||||
|
||||
# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
|
||||
# then it will generate one additional man file for each entity
|
||||
# documented in the real man page(s). These additional files
|
||||
# only source the real man page, but without them the man command
|
||||
# would be unable to find the correct page. The default is NO.
|
||||
|
||||
MAN_LINKS = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the XML output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the GENERATE_XML tag is set to YES Doxygen will
|
||||
# generate an XML file that captures the structure of
|
||||
# the code including all documentation. Note that this
|
||||
# feature is still experimental and incomplete at the
|
||||
# moment.
|
||||
|
||||
GENERATE_XML = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the preprocessor
|
||||
#---------------------------------------------------------------------------
|
||||
ENABLE_PREPROCESSING = NO
|
||||
|
||||
# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
|
||||
# evaluate all C-preprocessor directives found in the sources and include
|
||||
# files.
|
||||
|
||||
ENABLE_PREPROCESSING = YES
|
||||
|
||||
# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
|
||||
# names in the source code. If set to NO (the default) only conditional
|
||||
# compilation will be performed. Macro expansion can be done in a controlled
|
||||
# way by setting EXPAND_ONLY_PREDEF to YES.
|
||||
|
||||
MACRO_EXPANSION = NO
|
||||
|
||||
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
|
||||
# then the macro expansion is limited to the macros specified with the
|
||||
# PREDEFINED and EXPAND_AS_PREDEFINED tags.
|
||||
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
|
||||
# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
|
||||
# in the INCLUDE_PATH (see below) will be search if a #include is found.
|
||||
|
||||
SEARCH_INCLUDES = YES
|
||||
|
||||
# The INCLUDE_PATH tag can be used to specify one or more directories that
|
||||
# contain include files that are not input files but should be processed by
|
||||
# the preprocessor.
|
||||
|
||||
INCLUDE_PATH =
|
||||
|
||||
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
|
||||
# patterns (like *.h and *.hpp) to filter out the header-files in the
|
||||
# directories. If left blank, the patterns specified with FILE_PATTERNS will
|
||||
# be used.
|
||||
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
|
||||
# The PREDEFINED tag can be used to specify one or more macro names that
|
||||
# are defined before the preprocessor is started (similar to the -D option of
|
||||
# gcc). The argument of the tag is a list of macros of the form: name
|
||||
# or name=definition (no spaces). If the definition and the = are
|
||||
# omitted =1 is assumed.
|
||||
|
||||
PREDEFINED =
|
||||
|
||||
# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then
|
||||
# this tag can be used to specify a list of macro names that should be expanded.
|
||||
# The macro definition that is found in the sources will be used.
|
||||
# Use the PREDEFINED tag if you want to use a different macro definition.
|
||||
|
||||
EXPAND_AS_DEFINED =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration::addtions related to external references
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# The TAGFILES tag can be used to specify one or more tagfiles.
|
||||
|
||||
TAGFILES =
|
||||
|
||||
# When a file name is specified after GENERATE_TAGFILE, doxygen will create
|
||||
# a tag file that is based on the input files it reads.
|
||||
|
||||
GENERATE_TAGFILE =
|
||||
|
||||
# If the ALLEXTERNALS tag is set to YES all external classes will be listed
|
||||
# in the class index. If set to NO only the inherited external classes
|
||||
# will be listed.
|
||||
|
||||
ALLEXTERNALS = NO
|
||||
|
||||
# The PERL_PATH should be the absolute path and name of the perl script
|
||||
# interpreter (i.e. the result of `which perl').
|
||||
|
||||
PERL_PATH = /usr/bin/perl
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
HAVE_DOT = NO
|
||||
|
||||
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
|
||||
# available from the path. This tool is part of Graphviz, a graph visualization
|
||||
# toolkit from AT&T and Lucent Bell Labs. The other options in this section
|
||||
# have no effect if this option is set to NO (the default)
|
||||
|
||||
HAVE_DOT = YES
|
||||
|
||||
# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
|
||||
# will generate a graph for each documented class showing the direct and
|
||||
# indirect inheritance relations. Setting this tag to YES will force the
|
||||
# the CLASS_DIAGRAMS tag to NO.
|
||||
|
||||
CLASS_GRAPH = YES
|
||||
|
||||
# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
|
||||
# will generate a graph for each documented class showing the direct and
|
||||
# indirect implementation dependencies (inheritance, containment, and
|
||||
# class references variables) of the class with other documented classes.
|
||||
|
||||
COLLABORATION_GRAPH = YES
|
||||
|
||||
# If set to YES, the inheritance and collaboration graphs will show the
|
||||
# relations between templates and their instances.
|
||||
|
||||
TEMPLATE_RELATIONS = YES
|
||||
|
||||
# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
|
||||
# tags are set to YES then doxygen will generate a graph for each documented
|
||||
# file showing the direct and indirect include dependencies of the file with
|
||||
# other documented files.
|
||||
|
||||
INCLUDE_GRAPH = YES
|
||||
|
||||
# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
|
||||
# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
|
||||
# documented header file showing the documented files that directly or
|
||||
# indirectly include this file.
|
||||
|
||||
INCLUDED_BY_GRAPH = YES
|
||||
|
||||
# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
|
||||
# will graphical hierarchy of all classes instead of a textual one.
|
||||
|
||||
GRAPHICAL_HIERARCHY = YES
|
||||
|
||||
# The tag DOT_PATH can be used to specify the path where the dot tool can be
|
||||
# found. If left blank, it is assumed the dot tool can be found on the path.
|
||||
|
||||
DOT_PATH =
|
||||
|
||||
# The DOTFILE_DIRS tag can be used to specify one or more directories that
|
||||
# contain dot files that are included in the documentation (see the
|
||||
# \dotfile command).
|
||||
|
||||
DOTFILE_DIRS =
|
||||
|
||||
# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
|
||||
# (in pixels) of the graphs generated by dot. If a graph becomes larger than
|
||||
# this value, doxygen will try to truncate the graph, so that it fits within
|
||||
# the specified constraint. Beware that most browsers cannot cope with very
|
||||
# large images.
|
||||
|
||||
MAX_DOT_GRAPH_WIDTH = 1024
|
||||
|
||||
# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
|
||||
# (in pixels) of the graphs generated by dot. If a graph becomes larger than
|
||||
# this value, doxygen will try to truncate the graph, so that it fits within
|
||||
# the specified constraint. Beware that most browsers cannot cope with very
|
||||
# large images.
|
||||
|
||||
MAX_DOT_GRAPH_HEIGHT = 1024
|
||||
|
||||
# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
|
||||
# generate a legend page explaining the meaning of the various boxes and
|
||||
# arrows in the dot generated graphs.
|
||||
|
||||
GENERATE_LEGEND = YES
|
||||
|
||||
# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
|
||||
# remove the intermedate dot files that are used to generate
|
||||
# the various graphs.
|
||||
|
||||
DOT_CLEANUP = YES
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration::addtions related to the search engine
|
||||
#---------------------------------------------------------------------------
|
||||
SEARCHENGINE = NO
|
||||
CGI_NAME = search.cgi
|
||||
CGI_URL = http://localhost/cgi-bin
|
||||
DOC_URL = http://localhost/asterisk/documentation
|
||||
DOC_ABSPATH = /var/www/html/asterisk/documentation
|
||||
BIN_ABSPATH = /usr/local/bin
|
||||
EXT_DOC_PATHS =
|
||||
|
||||
# The SEARCHENGINE tag specifies whether or not a search engine should be
|
||||
# used. If set to NO the values of all tags below this one will be ignored.
|
||||
|
||||
SEARCHENGINE = NO
|
||||
|
||||
# The CGI_NAME tag should be the name of the CGI script that
|
||||
# starts the search engine (doxysearch) with the correct parameters.
|
||||
# A script with this name will be generated by doxygen.
|
||||
|
||||
CGI_NAME =
|
||||
|
||||
# The CGI_URL tag should be the absolute URL to the directory where the
|
||||
# cgi binaries are located. See the documentation of your http daemon for
|
||||
# details.
|
||||
|
||||
CGI_URL =
|
||||
|
||||
# The DOC_URL tag should be the absolute URL to the directory where the
|
||||
# documentation is located. If left blank the absolute path to the
|
||||
# documentation, with file:// prepended to it, will be used.
|
||||
|
||||
DOC_URL =
|
||||
|
||||
# The DOC_ABSPATH tag should be the absolute path to the directory where the
|
||||
# documentation is located. If left blank the directory on the local machine
|
||||
# will be used.
|
||||
|
||||
DOC_ABSPATH =
|
||||
|
||||
# The BIN_ABSPATH tag must point to the directory where the doxysearch binary
|
||||
# is installed.
|
||||
|
||||
BIN_ABSPATH =
|
||||
|
||||
# The EXT_DOC_PATHS tag can be used to specify one or more paths to
|
||||
# documentation generated for other projects. This allows doxysearch to search
|
||||
# the documentation for these projects as well.
|
||||
|
||||
EXT_DOC_PATHS =
|
||||
|
||||
302
asterisk.c
302
asterisk.c
@@ -18,13 +18,17 @@
|
||||
#include <asterisk/cli.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/ulaw.h>
|
||||
#include <asterisk/alaw.h>
|
||||
#include <asterisk/callerid.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/image.h>
|
||||
#include <asterisk/tdd.h>
|
||||
#include <asterisk/term.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <sched.h>
|
||||
#include <asterisk/io.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
@@ -46,6 +50,8 @@ int option_console=0;
|
||||
int option_highpriority=0;
|
||||
int option_remote=0;
|
||||
int option_exec=0;
|
||||
int option_initcrypto=0;
|
||||
int option_nocolor;
|
||||
int fully_booted = 0;
|
||||
|
||||
static int ast_socket = -1; /* UNIX Socket for allowing remote control */
|
||||
@@ -87,7 +93,7 @@ static void *netconsole(void *vconsole)
|
||||
fd_set rfds;
|
||||
|
||||
if (gethostname(hostname, sizeof(hostname)))
|
||||
strncpy(hostname, "<Unknown>", sizeof(hostname));
|
||||
strncpy(hostname, "<Unknown>", sizeof(hostname)-1);
|
||||
snprintf(tmp, sizeof(tmp), "%s/%d/%s\n", hostname, mainpid, ASTERISK_VERSION);
|
||||
fdprint(con->fd, tmp);
|
||||
for(;;) {
|
||||
@@ -196,7 +202,7 @@ static int ast_makesocket(void)
|
||||
}
|
||||
memset(&sun, 0, sizeof(sun));
|
||||
sun.sun_family = AF_LOCAL;
|
||||
strncpy(sun.sun_path, AST_SOCKET, sizeof(sun.sun_path));
|
||||
strncpy(sun.sun_path, AST_SOCKET, sizeof(sun.sun_path)-1);
|
||||
res = bind(ast_socket, (struct sockaddr *)&sun, sizeof(sun));
|
||||
if (res) {
|
||||
ast_log(LOG_WARNING, "Unable to bind socket to %s: %s\n", AST_SOCKET, strerror(errno));
|
||||
@@ -227,7 +233,7 @@ static int ast_tryconnect(void)
|
||||
}
|
||||
memset(&sun, 0, sizeof(sun));
|
||||
sun.sun_family = AF_LOCAL;
|
||||
strncpy(sun.sun_path, AST_SOCKET, sizeof(sun.sun_path));
|
||||
strncpy(sun.sun_path, AST_SOCKET, sizeof(sun.sun_path)-1);
|
||||
res = connect(ast_consock, (struct sockaddr *)&sun, sizeof(sun));
|
||||
if (res) {
|
||||
close(ast_consock);
|
||||
@@ -296,9 +302,55 @@ static int set_priority(int pri)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void quit_handler(int num)
|
||||
static char *_argv[256];
|
||||
|
||||
static int shuttingdown = 0;
|
||||
|
||||
static void quit_handler(int num, int nice, int safeshutdown, int restart)
|
||||
{
|
||||
char filename[80] = "";
|
||||
time_t s,e;
|
||||
int x;
|
||||
if (safeshutdown) {
|
||||
shuttingdown = 1;
|
||||
if (!nice) {
|
||||
/* Begin shutdown routine, hanging up active channels */
|
||||
ast_begin_shutdown(1);
|
||||
if (option_verbose && option_console)
|
||||
ast_verbose("Beginning asterisk %s....\n", restart ? "restart" : "shutdown");
|
||||
time(&s);
|
||||
for(;;) {
|
||||
time(&e);
|
||||
/* Wait up to 15 seconds for all channels to go away */
|
||||
if ((e - s) > 15)
|
||||
break;
|
||||
if (!ast_active_channels())
|
||||
break;
|
||||
if (!shuttingdown)
|
||||
break;
|
||||
/* Sleep 1/10 of a second */
|
||||
usleep(100000);
|
||||
}
|
||||
} else {
|
||||
if (nice < 2)
|
||||
ast_begin_shutdown(0);
|
||||
if (option_verbose && option_console)
|
||||
ast_verbose("Waiting for inactivity to perform %s...\n", restart ? "restart" : "halt");
|
||||
for(;;) {
|
||||
if (!ast_active_channels())
|
||||
break;
|
||||
if (!shuttingdown)
|
||||
break;
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!shuttingdown) {
|
||||
if (option_verbose && option_console)
|
||||
ast_verbose("Asterisk %s cancelled.\n", restart ? "restart" : "shutdown");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (option_console || option_remote) {
|
||||
if (getenv("HOME"))
|
||||
snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
|
||||
@@ -308,7 +360,7 @@ static void quit_handler(int num)
|
||||
}
|
||||
/* Called on exit */
|
||||
if (option_verbose && option_console)
|
||||
ast_verbose("Asterisk ending (%d).\n", num);
|
||||
ast_verbose("Asterisk %s ending (%d).\n", ast_active_channels() ? "uncleanly" : "cleanly", num);
|
||||
else if (option_debug)
|
||||
ast_log(LOG_DEBUG, "Asterisk ending (%d).\n", num);
|
||||
if (ast_socket > -1)
|
||||
@@ -317,18 +369,51 @@ static void quit_handler(int num)
|
||||
close(ast_consock);
|
||||
if (ast_socket > -1)
|
||||
unlink(AST_SOCKET);
|
||||
|
||||
exit(0);
|
||||
printf(term_quit());
|
||||
if (restart) {
|
||||
if (option_verbose || option_console)
|
||||
ast_verbose("Preparing for Asterisk restart...\n");
|
||||
/* Mark all FD's for closing on exec */
|
||||
for (x=3;x<32768;x++) {
|
||||
fcntl(x, F_SETFD, FD_CLOEXEC);
|
||||
}
|
||||
if (option_verbose || option_console)
|
||||
ast_verbose("Restarting Asterisk NOW...\n");
|
||||
execvp(_argv[0], _argv);
|
||||
} else
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void __quit_handler(int num)
|
||||
{
|
||||
quit_handler(num, 0, 1, 0);
|
||||
}
|
||||
|
||||
static pthread_t consolethread = -1;
|
||||
|
||||
static int fix_header(char *outbuf, int maxout, char **s, char *cmp)
|
||||
{
|
||||
if (!strncmp(*s, cmp, strlen(cmp))) {
|
||||
*s += strlen(cmp);
|
||||
term_color(outbuf, cmp, COLOR_GRAY, 0, maxout);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void console_verboser(char *s, int pos, int replace, int complete)
|
||||
{
|
||||
char tmp[80];
|
||||
/* Return to the beginning of the line */
|
||||
if (!pos)
|
||||
if (!pos) {
|
||||
fprintf(stdout, "\r");
|
||||
fprintf(stdout, s + pos);
|
||||
if (fix_header(tmp, sizeof(tmp), &s, VERBOSE_PREFIX_4) ||
|
||||
fix_header(tmp, sizeof(tmp), &s, VERBOSE_PREFIX_3) ||
|
||||
fix_header(tmp, sizeof(tmp), &s, VERBOSE_PREFIX_2) ||
|
||||
fix_header(tmp, sizeof(tmp), &s, VERBOSE_PREFIX_1))
|
||||
fputs(tmp, stdout);
|
||||
}
|
||||
fputs(s + pos,stdout);
|
||||
fflush(stdout);
|
||||
if (complete)
|
||||
/* Wake up a select()ing console */
|
||||
@@ -337,6 +422,8 @@ static void console_verboser(char *s, int pos, int replace, int complete)
|
||||
|
||||
static void consolehandler(char *s)
|
||||
{
|
||||
printf(term_end());
|
||||
fflush(stdout);
|
||||
/* Called when readline data is available */
|
||||
if (s && strlen(s))
|
||||
add_history(s);
|
||||
@@ -371,11 +458,11 @@ static void remoteconsolehandler(char *s)
|
||||
else
|
||||
system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
|
||||
} else
|
||||
strncpy(cmd, s, sizeof(cmd));
|
||||
strncpy(cmd, s, sizeof(cmd)-1);
|
||||
if (!strcasecmp(s, "help"))
|
||||
fprintf(stdout, " !<command> Executes a given shell command\n");
|
||||
if (!strcasecmp(s, "quit"))
|
||||
quit_handler(0);
|
||||
quit_handler(0, 0, 0, 0);
|
||||
} else
|
||||
fprintf(stdout, "\nUse \"quit\" to exit\n");
|
||||
}
|
||||
@@ -384,15 +471,88 @@ static char quit_help[] =
|
||||
"Usage: quit\n"
|
||||
" Exits Asterisk.\n";
|
||||
|
||||
static char shutdown_help[] =
|
||||
"Usage: shutdown\n"
|
||||
" Shuts down a running Asterisk PBX.\n";
|
||||
static char abort_halt_help[] =
|
||||
"Usage: abort shutdown\n"
|
||||
" Causes Asterisk to abort an executing shutdown or restart, and resume normal\n"
|
||||
" call operations.\n";
|
||||
|
||||
static char shutdown_now_help[] =
|
||||
"Usage: shutdown now\n"
|
||||
" Shuts down a running Asterisk immediately, hanging up all active calls .\n";
|
||||
|
||||
static char shutdown_gracefully_help[] =
|
||||
"Usage: shutdown gracefully\n"
|
||||
" Causes Asterisk to not accept new calls, and exit when all\n"
|
||||
" active calls have terminated normally.\n";
|
||||
|
||||
static char restart_now_help[] =
|
||||
"Usage: restart now\n"
|
||||
" Causes Asterisk to hangup all calls and exec() itself performing a cold.\n"
|
||||
" restart.\n";
|
||||
|
||||
static char restart_gracefully_help[] =
|
||||
"Usage: restart gracefully\n"
|
||||
" Causes Asterisk to stop accepting new calls and exec() itself performing a cold.\n"
|
||||
" restart when all active calls have ended.\n";
|
||||
|
||||
static char restart_when_convenient_help[] =
|
||||
"Usage: restart when convenient\n"
|
||||
" Causes Asterisk to perform a cold restart when all active calls have ended.\n";
|
||||
|
||||
static int handle_quit(int fd, int argc, char *argv[])
|
||||
{
|
||||
if (argc != 1)
|
||||
return RESULT_SHOWUSAGE;
|
||||
quit_handler(0);
|
||||
quit_handler(0, 0, 1, 0);
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static int handle_shutdown_now(int fd, int argc, char *argv[])
|
||||
{
|
||||
if (argc != 2)
|
||||
return RESULT_SHOWUSAGE;
|
||||
quit_handler(0, 0 /* Not nice */, 1 /* safely */, 0 /* not restart */);
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static int handle_shutdown_gracefully(int fd, int argc, char *argv[])
|
||||
{
|
||||
if (argc != 2)
|
||||
return RESULT_SHOWUSAGE;
|
||||
quit_handler(0, 1 /* nicely */, 1 /* safely */, 0 /* no restart */);
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static int handle_restart_now(int fd, int argc, char *argv[])
|
||||
{
|
||||
if (argc != 2)
|
||||
return RESULT_SHOWUSAGE;
|
||||
quit_handler(0, 0 /* not nicely */, 1 /* safely */, 1 /* restart */);
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static int handle_restart_gracefully(int fd, int argc, char *argv[])
|
||||
{
|
||||
if (argc != 2)
|
||||
return RESULT_SHOWUSAGE;
|
||||
quit_handler(0, 1 /* nicely */, 1 /* safely */, 1 /* restart */);
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static int handle_restart_when_convenient(int fd, int argc, char *argv[])
|
||||
{
|
||||
if (argc != 3)
|
||||
return RESULT_SHOWUSAGE;
|
||||
quit_handler(0, 2 /* really nicely */, 1 /* safely */, 1 /* restart */);
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static int handle_abort_halt(int fd, int argc, char *argv[])
|
||||
{
|
||||
if (argc != 2)
|
||||
return RESULT_SHOWUSAGE;
|
||||
ast_cancel_shutdown();
|
||||
shuttingdown = 0;
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -400,9 +560,15 @@ static int handle_quit(int fd, int argc, char *argv[])
|
||||
|
||||
#define ASTERISK_PROMPT2 "%s*CLI> "
|
||||
|
||||
static struct ast_cli_entry aborthalt = { { "abort", "halt", NULL }, handle_abort_halt, "Cancel a running halt", abort_halt_help };
|
||||
|
||||
static struct ast_cli_entry quit = { { "quit", NULL }, handle_quit, "Exit Asterisk", quit_help };
|
||||
|
||||
static struct ast_cli_entry astshutdown = { { "shutdown", NULL }, handle_quit, "Shut down an Asterisk PBX", shutdown_help };
|
||||
static struct ast_cli_entry astshutdownnow = { { "shutdown", "now", NULL }, handle_shutdown_now, "Shut down Asterisk imediately", shutdown_now_help };
|
||||
static struct ast_cli_entry astshutdowngracefully = { { "shutdown", "gracefully", NULL }, handle_shutdown_gracefully, "Gracefully shut down Asterisk", shutdown_gracefully_help };
|
||||
static struct ast_cli_entry astrestartnow = { { "restart", "now", NULL }, handle_restart_now, "Restart Asterisk immediately", restart_now_help };
|
||||
static struct ast_cli_entry astrestartgracefully = { { "restart", "gracefully", NULL }, handle_restart_gracefully, "Restart Asterisk gracefully", restart_gracefully_help };
|
||||
static struct ast_cli_entry astrestartwhenconvenient= { { "restart", "when", "convenient", NULL }, handle_restart_when_convenient, "Restart Asterisk at empty call volume", restart_when_convenient_help };
|
||||
|
||||
static char *cli_generator(char *text, int state)
|
||||
{
|
||||
@@ -441,6 +607,8 @@ static void ast_remotecontrol(char * data)
|
||||
char *cpid;
|
||||
char *version;
|
||||
int pid;
|
||||
int lastclear=0;
|
||||
int oldstatus=0;
|
||||
char tmp[80];
|
||||
read(ast_consock, buf, sizeof(buf));
|
||||
if (data) {
|
||||
@@ -465,8 +633,10 @@ static void ast_remotecontrol(char * data)
|
||||
snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
|
||||
if (strlen(filename))
|
||||
read_history(filename);
|
||||
ast_cli_register(&quit);
|
||||
ast_cli_register(&astshutdown);
|
||||
ast_cli_register(&quit);
|
||||
#if 0
|
||||
ast_cli_register(&astshutdown);
|
||||
#endif
|
||||
rl_callback_handler_install(tmp, remoteconsolehandler);
|
||||
rl_completion_entry_function = (Function *)console_cli_generator;
|
||||
for(;;) {
|
||||
@@ -499,6 +669,18 @@ static void ast_remotecontrol(char * data)
|
||||
if (res < 1)
|
||||
break;
|
||||
buf[res] = 0;
|
||||
/* If someone asks for a pass code, hide the password */
|
||||
if (!memcmp(buf, ">>>>", 4)) {
|
||||
printf("Ooh, i should hide password!\n");
|
||||
if (!lastclear) {
|
||||
oldstatus = ast_hide_password(STDIN_FILENO);
|
||||
printf("Oldstatus = %d\n", oldstatus);
|
||||
}
|
||||
lastclear = 1;
|
||||
} else if (lastclear) {
|
||||
ast_restore_tty(STDIN_FILENO, oldstatus);
|
||||
lastclear = 0;
|
||||
}
|
||||
if (!lastpos)
|
||||
write(STDOUT_FILENO, "\r", 2);
|
||||
write(STDOUT_FILENO, buf, res);
|
||||
@@ -521,14 +703,27 @@ int main(int argc, char *argv[])
|
||||
int pid;
|
||||
char filename[80] = "";
|
||||
char hostname[256];
|
||||
char tmp[80];
|
||||
char * xarg = NULL;
|
||||
int x;
|
||||
sigset_t sigs;
|
||||
|
||||
/* Remember original args for restart */
|
||||
if (argc > sizeof(_argv) / sizeof(_argv[0]) - 1) {
|
||||
fprintf(stderr, "Truncating argument size to %d\n", sizeof(_argv) / sizeof(_argv[0]) - 1);
|
||||
argc = sizeof(_argv) / sizeof(_argv[0]) - 1;
|
||||
}
|
||||
for (x=0;x<argc;x++)
|
||||
_argv[x] = argv[x];
|
||||
_argv[x] = NULL;
|
||||
|
||||
if (gethostname(hostname, sizeof(hostname)))
|
||||
strncpy(hostname, "<Unknown>", sizeof(hostname));
|
||||
strncpy(hostname, "<Unknown>", sizeof(hostname)-1);
|
||||
mainpid = getpid();
|
||||
ast_ulaw_init();
|
||||
ast_alaw_init();
|
||||
callerid_init();
|
||||
tdd_init();
|
||||
if (getenv("HOME"))
|
||||
snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
|
||||
/* Check if we're root */
|
||||
@@ -537,7 +732,7 @@ int main(int argc, char *argv[])
|
||||
exit(1);
|
||||
}
|
||||
/* Check for options */
|
||||
while((c=getopt(argc, argv, "fdvqprcx:")) != EOF) {
|
||||
while((c=getopt(argc, argv, "fdvqprcinx:")) != EOF) {
|
||||
switch(c) {
|
||||
case 'd':
|
||||
option_debug++;
|
||||
@@ -550,6 +745,9 @@ int main(int argc, char *argv[])
|
||||
case 'f':
|
||||
option_nofork++;
|
||||
break;
|
||||
case 'n':
|
||||
option_nocolor++;
|
||||
break;
|
||||
case 'r':
|
||||
option_remote++;
|
||||
option_nofork++;
|
||||
@@ -568,43 +766,56 @@ int main(int argc, char *argv[])
|
||||
option_exec++;
|
||||
xarg = optarg;
|
||||
break;
|
||||
case 'i':
|
||||
option_initcrypto++;
|
||||
break;
|
||||
case '?':
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
term_init();
|
||||
printf(term_end());
|
||||
fflush(stdout);
|
||||
|
||||
if (ast_tryconnect()) {
|
||||
/* One is already running */
|
||||
if (option_remote) {
|
||||
if (option_exec) {
|
||||
ast_remotecontrol(xarg);
|
||||
quit_handler(0);
|
||||
quit_handler(0, 0, 0, 0);
|
||||
exit(0);
|
||||
}
|
||||
printf(term_quit());
|
||||
ast_register_verbose(console_verboser);
|
||||
ast_verbose( "Asterisk " ASTERISK_VERSION ", Copyright (C) 1999-2001 Linux Support Services, Inc.\n");
|
||||
ast_verbose( "Written by Mark Spencer <markster@linux-support.net>\n");
|
||||
ast_verbose( "=========================================================================\n");
|
||||
ast_remotecontrol(NULL);
|
||||
quit_handler(0);
|
||||
quit_handler(0, 0, 0, 0);
|
||||
exit(0);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Asterisk already running on %s. Use 'asterisk -r' to connect.\n", AST_SOCKET);
|
||||
printf(term_quit());
|
||||
exit(1);
|
||||
}
|
||||
} else if (option_remote || option_exec) {
|
||||
ast_log(LOG_ERROR, "Unable to connect to remote asterisk\n");
|
||||
printf(term_quit());
|
||||
exit(1);
|
||||
}
|
||||
if (!option_verbose && !option_console && !option_debug) {
|
||||
|
||||
if (!option_verbose && !option_debug && !option_nofork && !option_console) {
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
ast_log(LOG_ERROR, "Unable to fork(): %s\n", strerror(errno));
|
||||
printf(term_quit());
|
||||
exit(1);
|
||||
}
|
||||
if (pid)
|
||||
exit(0);
|
||||
}
|
||||
|
||||
ast_makesocket();
|
||||
sigemptyset(&sigs);
|
||||
sigaddset(&sigs, SIGHUP);
|
||||
@@ -624,31 +835,48 @@ int main(int argc, char *argv[])
|
||||
if (option_console && !option_verbose)
|
||||
ast_verbose("[ Booting...");
|
||||
signal(SIGURG, urg_handler);
|
||||
signal(SIGINT, quit_handler);
|
||||
signal(SIGTERM, quit_handler);
|
||||
signal(SIGINT, __quit_handler);
|
||||
signal(SIGTERM, __quit_handler);
|
||||
signal(SIGHUP, hup_handler);
|
||||
signal(SIGPIPE, pipe_handler);
|
||||
if (set_priority(option_highpriority))
|
||||
if (set_priority(option_highpriority)) {
|
||||
printf(term_quit());
|
||||
exit(1);
|
||||
if (init_logger())
|
||||
}
|
||||
if (init_logger()) {
|
||||
printf(term_quit());
|
||||
exit(1);
|
||||
if (ast_image_init())
|
||||
}
|
||||
if (ast_image_init()) {
|
||||
printf(term_quit());
|
||||
exit(1);
|
||||
if (load_pbx())
|
||||
}
|
||||
if (load_pbx()) {
|
||||
printf(term_quit());
|
||||
exit(1);
|
||||
if (load_modules())
|
||||
}
|
||||
if (load_modules()) {
|
||||
printf(term_quit());
|
||||
exit(1);
|
||||
if (init_framer())
|
||||
}
|
||||
if (init_framer()) {
|
||||
printf(term_quit());
|
||||
exit(1);
|
||||
}
|
||||
/* We might have the option of showing a console, but for now just
|
||||
do nothing... */
|
||||
if (option_console && !option_verbose)
|
||||
ast_verbose(" ]\n");
|
||||
if (option_verbose || option_console)
|
||||
ast_verbose( "Asterisk Ready.\n");
|
||||
ast_verbose(term_color(tmp, "Asterisk Ready.\n", COLOR_BRWHITE, COLOR_BLACK, sizeof(tmp)));
|
||||
fully_booted = 1;
|
||||
pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);
|
||||
ast_cli_register(&astshutdown);
|
||||
ast_cli_register(&astshutdownnow);
|
||||
ast_cli_register(&astshutdowngracefully);
|
||||
ast_cli_register(&astrestartnow);
|
||||
ast_cli_register(&astrestartgracefully);
|
||||
ast_cli_register(&astrestartwhenconvenient);
|
||||
ast_cli_register(&aborthalt);
|
||||
if (option_console) {
|
||||
/* Console stuff now... */
|
||||
/* Register our quit function */
|
||||
@@ -660,21 +888,25 @@ int main(int argc, char *argv[])
|
||||
consolethread = pthread_self();
|
||||
if (strlen(filename))
|
||||
read_history(filename);
|
||||
rl_callback_handler_install(ASTERISK_PROMPT, consolehandler);
|
||||
term_prompt(tmp, ASTERISK_PROMPT, sizeof(tmp));
|
||||
rl_callback_handler_install(tmp, consolehandler);
|
||||
rl_completion_entry_function = (Function *)cli_generator;
|
||||
for(;;) {
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(STDIN_FILENO, &rfds);
|
||||
res = select(STDIN_FILENO + 1, &rfds, NULL, NULL, NULL);
|
||||
if (res > 0) {
|
||||
printf(term_prep());
|
||||
rl_callback_read_char();
|
||||
printf(term_end());
|
||||
fflush(stdout);
|
||||
} else if (res < 1) {
|
||||
rl_forced_update_display();
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
/* Do nothing */
|
||||
/* Do nothing */
|
||||
select(0,NULL,NULL,NULL,NULL);
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#define AST_VAR_DIR "/var/lib/asterisk"
|
||||
#define AST_LOG_DIR "/var/log/asterisk"
|
||||
#define AST_AGI_DIR "/var/lib/asterisk/agi-bin"
|
||||
#define AST_KEY_DIR "/var/lib/asterisk/keys"
|
||||
|
||||
#define AST_CONFIG_FILE "asterisk.conf"
|
||||
|
||||
@@ -37,4 +38,8 @@ extern int load_pbx(void);
|
||||
extern int init_logger(void);
|
||||
/* Provided by frame.c */
|
||||
extern int init_framer(void);
|
||||
/* Provided by logger.c */
|
||||
extern int reload_logger(void);
|
||||
/* Provided by term.c */
|
||||
extern int term_init(void);
|
||||
#endif
|
||||
|
||||
47
astgenkey
Normal file
47
astgenkey
Normal file
@@ -0,0 +1,47 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Usage: astgenkey [ -q ] [keyname]
|
||||
#
|
||||
if [ "$1" = "-q" ]; then
|
||||
QUIET='y'
|
||||
KEY=$2
|
||||
else
|
||||
KEY=$1
|
||||
fi
|
||||
|
||||
if [ "$QUIET" != 'y' ]; then
|
||||
echo ""
|
||||
echo "This script generates an RSA private and public key pair"
|
||||
echo "in PEM format for use by Asterisk. You will be asked to"
|
||||
echo "enter a passcode for your key multiple times. Please"
|
||||
echo "enter the same code each time. The resulting files will"
|
||||
echo "need to be moved to /var/lib/asterisk/keys if you want"
|
||||
echo "to use them, and any private keys (.key files) will"
|
||||
echo "need to be initialized at runtime either by running"
|
||||
echo "Asterisk with the '-i' option, or with the 'init keys'"
|
||||
echo "command once Asterisk is running."
|
||||
echo ""
|
||||
echo "Press ENTER to continue or ^C to cancel."
|
||||
read BLAH
|
||||
fi
|
||||
|
||||
while [ "$KEY" = "" ]; do
|
||||
echo -n "Enter key name: "
|
||||
read KEY
|
||||
done
|
||||
|
||||
rm -f ${KEY}.key ${KEY}.pub
|
||||
|
||||
echo "Generating SSL key '$KEY': "
|
||||
openssl genrsa -out ${KEY}.key -des3 1024
|
||||
openssl rsa -in ${KEY}.key -pubout -out ${KEY}.pub
|
||||
|
||||
if [ -f "${KEY}.key" ] && [ -f "${KEY}.pub" ]; then
|
||||
if [ "$QUIET" != 'y' ]; then
|
||||
echo "Key creation successful."
|
||||
echo "Public key: ${KEY}.pub"
|
||||
echo "Private key: ${KEY}.key"
|
||||
fi
|
||||
else
|
||||
echo "Unknown error creating keys."
|
||||
fi
|
||||
96
callerid.c
96
callerid.c
@@ -43,8 +43,9 @@ struct callerid_state {
|
||||
int len;
|
||||
};
|
||||
|
||||
static float dr[4], di[4];
|
||||
static float clidsb = 8000.0 / 1200.0;
|
||||
|
||||
float cid_dr[4], cid_di[4];
|
||||
float clidsb = 8000.0 / 1200.0;
|
||||
|
||||
#define CALLERID_SPACE 2200.0 /* 2200 hz for "0" */
|
||||
#define CALLERID_MARK 1200.0 /* 1200 hz for "1" */
|
||||
@@ -52,10 +53,10 @@ static float clidsb = 8000.0 / 1200.0;
|
||||
void callerid_init(void)
|
||||
{
|
||||
/* Initialize stuff for inverse FFT */
|
||||
dr[0] = cos(CALLERID_SPACE * 2.0 * M_PI / 8000.0);
|
||||
di[0] = sin(CALLERID_SPACE * 2.0 * M_PI / 8000.0);
|
||||
dr[1] = cos(CALLERID_MARK * 2.0 * M_PI / 8000.0);
|
||||
di[1] = sin(CALLERID_MARK * 2.0 * M_PI / 8000.0);
|
||||
cid_dr[0] = cos(CALLERID_SPACE * 2.0 * M_PI / 8000.0);
|
||||
cid_di[0] = sin(CALLERID_SPACE * 2.0 * M_PI / 8000.0);
|
||||
cid_dr[1] = cos(CALLERID_MARK * 2.0 * M_PI / 8000.0);
|
||||
cid_di[1] = sin(CALLERID_MARK * 2.0 * M_PI / 8000.0);
|
||||
}
|
||||
|
||||
struct callerid_state *callerid_new(void)
|
||||
@@ -98,21 +99,23 @@ void callerid_get(struct callerid_state *cid, char **name, char **number, int *f
|
||||
*number = cid->number;
|
||||
}
|
||||
|
||||
int ast_callerid_gen_cas(unsigned char *outbuf, int len)
|
||||
int ast_gen_cas(unsigned char *outbuf, int sendsas, int len)
|
||||
{
|
||||
int pos = 0;
|
||||
int cnt;
|
||||
int saslen=2400;
|
||||
if (len < saslen)
|
||||
return -1;
|
||||
while(saslen) {
|
||||
cnt = saslen;
|
||||
if (cnt > sizeof(sas))
|
||||
cnt = sizeof(sas);
|
||||
memcpy(outbuf + pos, sas, cnt);
|
||||
pos += cnt;
|
||||
len -= cnt;
|
||||
saslen -= cnt;
|
||||
if (sendsas) {
|
||||
if (len < saslen)
|
||||
return -1;
|
||||
while(saslen) {
|
||||
cnt = saslen;
|
||||
if (cnt > sizeof(sas))
|
||||
cnt = sizeof(sas);
|
||||
memcpy(outbuf + pos, sas, cnt);
|
||||
pos += cnt;
|
||||
len -= cnt;
|
||||
saslen -= cnt;
|
||||
}
|
||||
}
|
||||
while(len) {
|
||||
cnt = len;
|
||||
@@ -142,7 +145,7 @@ int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len)
|
||||
memcpy(buf, cid->oldstuff, cid->oldlen);
|
||||
mylen += cid->oldlen/2;
|
||||
for (x=0;x<len;x++)
|
||||
buf[x+cid->oldlen/2] = ast_mulaw[ubuf[x]];
|
||||
buf[x+cid->oldlen/2] = AST_MULAW(ubuf[x]);
|
||||
while(mylen >= 80) {
|
||||
olen = mylen;
|
||||
res = fsk_serie(&cid->fskd, buf, &mylen, &b);
|
||||
@@ -239,7 +242,7 @@ int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len)
|
||||
}
|
||||
} else {
|
||||
/* SDMF */
|
||||
strncpy(cid->number, cid->rawdata + 8, sizeof(cid->number));
|
||||
strncpy(cid->number, cid->rawdata + 8, sizeof(cid->number)-1);
|
||||
}
|
||||
/* Update flags */
|
||||
cid->flags = 0;
|
||||
@@ -346,57 +349,6 @@ static void callerid_genmsg(char *msg, int size, char *number, char *name, int f
|
||||
|
||||
}
|
||||
|
||||
static inline float callerid_getcarrier(float *cr, float *ci, int bit)
|
||||
{
|
||||
/* Move along. There's nothing to see here... */
|
||||
float t;
|
||||
t = *cr * dr[bit] - *ci * di[bit];
|
||||
*ci = *cr * di[bit] + *ci * dr[bit];
|
||||
*cr = t;
|
||||
|
||||
t = 2.0 - (*cr * *cr + *ci * *ci);
|
||||
*cr *= t;
|
||||
*ci *= t;
|
||||
return *cr;
|
||||
}
|
||||
|
||||
#define PUT_BYTE(a) do { \
|
||||
*(buf++) = (a); \
|
||||
bytes++; \
|
||||
} while(0)
|
||||
|
||||
#define PUT_AUDIO_SAMPLE(y) do { \
|
||||
int index = (short)(rint(8192.0 * (y))); \
|
||||
*(buf++) = ast_lin2mu[index + 32768]; \
|
||||
bytes++; \
|
||||
} while(0)
|
||||
|
||||
#define PUT_CLID_MARKMS do { \
|
||||
int x; \
|
||||
for (x=0;x<8;x++) \
|
||||
PUT_AUDIO_SAMPLE(callerid_getcarrier(&cr, &ci, 1)); \
|
||||
} while(0)
|
||||
|
||||
#define PUT_CLID_BAUD(bit) do { \
|
||||
while(scont < clidsb) { \
|
||||
PUT_AUDIO_SAMPLE(callerid_getcarrier(&cr, &ci, bit)); \
|
||||
scont += 1.0; \
|
||||
} \
|
||||
scont -= clidsb; \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define PUT_CLID(byte) do { \
|
||||
int z; \
|
||||
unsigned char b = (byte); \
|
||||
PUT_CLID_BAUD(0); /* Start bit */ \
|
||||
for (z=0;z<8;z++) { \
|
||||
PUT_CLID_BAUD(b & 1); \
|
||||
b >>= 1; \
|
||||
} \
|
||||
PUT_CLID_BAUD(1); /* Stop bit */ \
|
||||
} while(0);
|
||||
|
||||
int callerid_generate(unsigned char *buf, char *number, char *name, int flags, int callwaiting)
|
||||
{
|
||||
int bytes=0;
|
||||
@@ -486,7 +438,7 @@ int ast_callerid_parse(char *instr, char **name, char **location)
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
strncpy(tmp, instr, sizeof(tmp));
|
||||
strncpy(tmp, instr, sizeof(tmp)-1);
|
||||
ast_shrink_phone_number(tmp);
|
||||
if (ast_isphonenumber(tmp)) {
|
||||
/* Assume it's just a location */
|
||||
@@ -508,7 +460,7 @@ static int __ast_callerid_generate(unsigned char *buf, char *callerid, int callw
|
||||
char *n, *l;
|
||||
if (!callerid)
|
||||
return callerid_generate(buf, NULL, NULL, 0, callwaiting);
|
||||
strncpy(tmp, callerid, sizeof(tmp));
|
||||
strncpy(tmp, callerid, sizeof(tmp)-1);
|
||||
if (ast_callerid_parse(tmp, &n, &l)) {
|
||||
ast_log(LOG_WARNING, "Unable to parse '%s' into CallerID name & number\n", callerid);
|
||||
return callerid_generate(buf, NULL, NULL, 0, callwaiting);
|
||||
|
||||
313
cdr.c
Normal file
313
cdr.c
Normal file
@@ -0,0 +1,313 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Call Detail Record API
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License.
|
||||
*
|
||||
* Includes code and algorithms from the Zapata library.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/cdr.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/callerid.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
int ast_default_amaflags = AST_CDR_DOCUMENTATION;
|
||||
char ast_default_accountcode[20] = "";
|
||||
|
||||
static pthread_mutex_t cdrlock = AST_MUTEX_INITIALIZER;
|
||||
|
||||
static struct ast_cdr_beitem {
|
||||
char name[20];
|
||||
char desc[80];
|
||||
ast_cdrbe be;
|
||||
struct ast_cdr_beitem *next;
|
||||
} *bes = NULL;
|
||||
|
||||
/*
|
||||
* We do a lot of checking here in the CDR code to try to be sure we don't ever let a CDR slip
|
||||
* through our fingers somehow. If someone allocates a CDR, it must be completely handled normally
|
||||
* or a WARNING shall be logged, so that we can best keep track of any escape condition where the CDR
|
||||
* isn't properly generated and posted.
|
||||
*/
|
||||
|
||||
int ast_cdr_register(char *name, char *desc, ast_cdrbe be)
|
||||
{
|
||||
struct ast_cdr_beitem *i;
|
||||
if (!name)
|
||||
return -1;
|
||||
if (!be) {
|
||||
ast_log(LOG_WARNING, "CDR engine '%s' lacks backend\n", name);
|
||||
return -1;
|
||||
}
|
||||
ast_pthread_mutex_lock(&cdrlock);
|
||||
i = bes;
|
||||
while(i) {
|
||||
if (!strcasecmp(name, i->name))
|
||||
break;
|
||||
i = i->next;
|
||||
}
|
||||
ast_pthread_mutex_unlock(&cdrlock);
|
||||
if (i) {
|
||||
ast_log(LOG_WARNING, "Already have a CDR backend called '%s'\n", name);
|
||||
return -1;
|
||||
}
|
||||
i = malloc(sizeof(struct ast_cdr_beitem));
|
||||
if (!i)
|
||||
return -1;
|
||||
memset(i, 0, sizeof(struct ast_cdr_beitem));
|
||||
strncpy(i->name, name, sizeof(i->name) - 1);
|
||||
strncpy(i->desc, desc, sizeof(i->desc) - 1);
|
||||
i->be = be;
|
||||
ast_pthread_mutex_lock(&cdrlock);
|
||||
i->next = bes;
|
||||
bes = i;
|
||||
ast_pthread_mutex_unlock(&cdrlock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ast_cdr_unregister(char *name)
|
||||
{
|
||||
struct ast_cdr_beitem *i, *prev = NULL;
|
||||
ast_pthread_mutex_lock(&cdrlock);
|
||||
i = bes;
|
||||
while(i) {
|
||||
if (!strcasecmp(name, i->name)) {
|
||||
if (prev)
|
||||
prev->next = i->next;
|
||||
else
|
||||
bes = i->next;
|
||||
break;
|
||||
}
|
||||
i = i->next;
|
||||
}
|
||||
ast_pthread_mutex_unlock(&cdrlock);
|
||||
if (i)
|
||||
free(i);
|
||||
}
|
||||
|
||||
void ast_cdr_free(struct ast_cdr *cdr)
|
||||
{
|
||||
char *chan;
|
||||
if (cdr) {
|
||||
chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
|
||||
if (!cdr->posted)
|
||||
ast_log(LOG_WARNING, "CDR on channel '%s' not posted\n", chan);
|
||||
if (!cdr->end.tv_sec && !cdr->end.tv_usec)
|
||||
ast_log(LOG_WARNING, "CDR on channel '%s' lacks end\n", chan);
|
||||
if (!cdr->start.tv_sec && !cdr->start.tv_usec)
|
||||
ast_log(LOG_WARNING, "CDR on channel '%s' lacks start\n", chan);
|
||||
free(cdr);
|
||||
}
|
||||
}
|
||||
|
||||
struct ast_cdr *ast_cdr_alloc(void)
|
||||
{
|
||||
struct ast_cdr *cdr;
|
||||
cdr = malloc(sizeof(struct ast_cdr));
|
||||
if (cdr) {
|
||||
memset(cdr, 0, sizeof(struct ast_cdr));
|
||||
}
|
||||
return cdr;
|
||||
}
|
||||
|
||||
void ast_cdr_start(struct ast_cdr *cdr)
|
||||
{
|
||||
char *chan;
|
||||
if (cdr) {
|
||||
chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
|
||||
if (cdr->posted)
|
||||
ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
|
||||
if (cdr->start.tv_sec || cdr->start.tv_usec)
|
||||
ast_log(LOG_WARNING, "CDR on channel '%s' already started\n", chan);
|
||||
gettimeofday(&cdr->start, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void ast_cdr_answer(struct ast_cdr *cdr)
|
||||
{
|
||||
char *chan;
|
||||
if (cdr) {
|
||||
chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
|
||||
if (cdr->posted)
|
||||
ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
|
||||
if (cdr->disposition < AST_CDR_ANSWERED)
|
||||
cdr->disposition = AST_CDR_ANSWERED;
|
||||
if (!cdr->answer.tv_sec && !cdr->answer.tv_usec) {
|
||||
gettimeofday(&cdr->answer, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ast_cdr_busy(struct ast_cdr *cdr)
|
||||
{
|
||||
char *chan;
|
||||
if (cdr) {
|
||||
chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
|
||||
if (cdr->posted)
|
||||
ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
|
||||
if (cdr->disposition < AST_CDR_BUSY)
|
||||
cdr->disposition = AST_CDR_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
void ast_cdr_setdestchan(struct ast_cdr *cdr, char *chann)
|
||||
{
|
||||
char *chan;
|
||||
if (cdr) {
|
||||
chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
|
||||
if (cdr->posted)
|
||||
ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
|
||||
strncpy(cdr->dstchannel, chann, sizeof(cdr->dstchannel) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void ast_cdr_setapp(struct ast_cdr *cdr, char *app, char *data)
|
||||
{
|
||||
char *chan;
|
||||
if (cdr) {
|
||||
chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
|
||||
if (cdr->posted)
|
||||
ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
|
||||
if (!app)
|
||||
app = "";
|
||||
strncpy(cdr->lastapp, app, sizeof(cdr->lastapp) - 1);
|
||||
if (!data)
|
||||
data = "";
|
||||
strncpy(cdr->lastdata, data, sizeof(cdr->lastdata) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
int ast_cdr_init(struct ast_cdr *cdr, struct ast_channel *c)
|
||||
{
|
||||
char *chan;
|
||||
char *num, *name;
|
||||
char tmp[AST_MAX_EXTENSION];
|
||||
if (cdr) {
|
||||
chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
|
||||
if (strlen(cdr->channel))
|
||||
ast_log(LOG_WARNING, "CDR already initialized on '%s'\n", chan);
|
||||
strncpy(cdr->channel, c->name, sizeof(cdr->channel) - 1);
|
||||
/* Grab source from ANI or normal Caller*ID */
|
||||
if (c->ani)
|
||||
strncpy(tmp, c->ani, sizeof(tmp) - 1);
|
||||
else if (c->callerid)
|
||||
strncpy(tmp, c->callerid, sizeof(tmp) - 1);
|
||||
if (c->callerid)
|
||||
strncpy(cdr->clid, c->callerid, sizeof(cdr->clid) - 1);
|
||||
name = NULL;
|
||||
num = NULL;
|
||||
ast_callerid_parse(tmp, &name, &num);
|
||||
if (num) {
|
||||
ast_shrink_phone_number(num);
|
||||
strncpy(cdr->src, num, sizeof(cdr->src) - 1);
|
||||
}
|
||||
|
||||
if (c->state == AST_STATE_UP)
|
||||
cdr->disposition = AST_CDR_ANSWERED;
|
||||
else
|
||||
cdr->disposition = AST_CDR_NOANSWER;
|
||||
if (c->amaflags)
|
||||
cdr->amaflags = c->amaflags;
|
||||
else
|
||||
cdr->amaflags = ast_default_amaflags;
|
||||
strncpy(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode) - 1);
|
||||
/* Destination information */
|
||||
strncpy(cdr->dst, c->exten, sizeof(cdr->dst) - 1);
|
||||
strncpy(cdr->dcontext, c->context, sizeof(cdr->dcontext) - 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ast_cdr_end(struct ast_cdr *cdr)
|
||||
{
|
||||
char *chan;
|
||||
if (cdr) {
|
||||
chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
|
||||
if (cdr->posted)
|
||||
ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
|
||||
if (!cdr->start.tv_sec && !cdr->start.tv_usec)
|
||||
ast_log(LOG_WARNING, "CDR on channel '%s' has not started\n", chan);
|
||||
if (!cdr->end.tv_sec && !cdr->end.tv_usec)
|
||||
gettimeofday(&cdr->end, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
char *ast_cdr_disp2str(int disposition)
|
||||
{
|
||||
switch (disposition) {
|
||||
case AST_CDR_NOANSWER:
|
||||
return "NO ANSWER";
|
||||
case AST_CDR_BUSY:
|
||||
return "BUSY";
|
||||
case AST_CDR_ANSWERED:
|
||||
return "ANSWERED";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
char *ast_cdr_flags2str(int flag)
|
||||
{
|
||||
switch(flag) {
|
||||
case AST_CDR_OMIT:
|
||||
return "OMIT";
|
||||
case AST_CDR_BILLING:
|
||||
return "BILLING";
|
||||
case AST_CDR_DOCUMENTATION:
|
||||
return "DOCUMENTATION";
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
int ast_cdr_amaflags2int(char *flag)
|
||||
{
|
||||
if (!strcasecmp(flag, "default"))
|
||||
return 0;
|
||||
if (!strcasecmp(flag, "omit"))
|
||||
return AST_CDR_OMIT;
|
||||
if (!strcasecmp(flag, "billing"))
|
||||
return AST_CDR_BILLING;
|
||||
if (!strcasecmp(flag, "documentation"))
|
||||
return AST_CDR_DOCUMENTATION;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ast_cdr_post(struct ast_cdr *cdr)
|
||||
{
|
||||
char *chan;
|
||||
struct ast_cdr_beitem *i;
|
||||
if (cdr) {
|
||||
chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
|
||||
if (cdr->posted)
|
||||
ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
|
||||
if (!cdr->end.tv_sec && !cdr->end.tv_usec)
|
||||
ast_log(LOG_WARNING, "CDR on channel '%s' lacks end\n", chan);
|
||||
if (!cdr->start.tv_sec && !cdr->start.tv_usec)
|
||||
ast_log(LOG_WARNING, "CDR on channel '%s' lacks start\n", chan);
|
||||
cdr->duration = cdr->end.tv_sec - cdr->start.tv_sec + (cdr->end.tv_usec - cdr->start.tv_usec) / 1000000;
|
||||
if (cdr->answer.tv_sec || cdr->answer.tv_usec) {
|
||||
cdr->billsec = cdr->end.tv_sec - cdr->answer.tv_sec + (cdr->end.tv_usec - cdr->answer.tv_usec) / 1000000;
|
||||
} else
|
||||
cdr->billsec = 0;
|
||||
cdr->posted = 1;
|
||||
ast_pthread_mutex_lock(&cdrlock);
|
||||
i = bes;
|
||||
while(i) {
|
||||
i->be(cdr);
|
||||
i = i->next;
|
||||
}
|
||||
ast_pthread_mutex_unlock(&cdrlock);
|
||||
}
|
||||
}
|
||||
43
cdr/Makefile
Normal file
43
cdr/Makefile
Normal file
@@ -0,0 +1,43 @@
|
||||
#
|
||||
# Asterisk -- A telephony toolkit for Linux.
|
||||
#
|
||||
# Makefile for CDR backends (dynamically loaded)
|
||||
#
|
||||
# Copyright (C) 1999, Mark Spencer
|
||||
#
|
||||
# Mark Spencer <markster@linux-support.net>
|
||||
#
|
||||
# This program is free software, distributed under the terms of
|
||||
# the GNU General Public License
|
||||
#
|
||||
|
||||
MODS=cdr_csv.so
|
||||
|
||||
CFLAGS+=
|
||||
|
||||
#
|
||||
# MySQL stuff... Autoconf anyone??
|
||||
#
|
||||
MODS+=$(shell if [ -d /usr/lib/mysql ] || \
|
||||
[`ls /usr/lib/libmysqlclient.so* 2>/dev/null | wc -l` -gt 0 ] || \
|
||||
[`ls /usr/local/lib/libmysqlclient.so* 2>/dev/null | wc -l` -gt 0 ] \
|
||||
; then echo "cdr_mysql.so" ; fi)
|
||||
CFLAGS+=$(shell if [ -d /usr/include/mysql ]; then echo "-I/usr/include/mysql"; fi)
|
||||
CFLAGS+=$(shell if [ -d /usr/local/include/mysql ]; then echo "-I/usr/local/include/mysql"; fi)
|
||||
MLFLAGS=
|
||||
MLFLAGS+=$(shell if [ -d /usr/lib/mysql ]; then echo "-L/usr/lib/mysql"; fi)
|
||||
MLFLAGS+=$(shell if [ -d /usr/local/lib/mysql ]; then echo "-L/usr/local/lib/mysql"; fi)
|
||||
|
||||
all: $(MODS)
|
||||
|
||||
install: all
|
||||
for x in $(MODS); do $(INSTALL) -m 755 $$x $(MODULES_DIR) ; done
|
||||
|
||||
clean:
|
||||
rm -f *.so *.o
|
||||
|
||||
%.so : %.o
|
||||
$(CC) -shared -Xlinker -x -o $@ $<
|
||||
|
||||
cdr_mysql.so: cdr_mysql.o
|
||||
$(CC) -shared -Xlinker -x -o $@ $< -lmysqlclient $(MLFLAGS)
|
||||
253
cdr/cdr_csv.c
Normal file
253
cdr/cdr_csv.c
Normal file
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Comma Separated Value CDR records.
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License.
|
||||
*
|
||||
* Includes code and algorithms from the Zapata library.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/cdr.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include "../asterisk.h"
|
||||
|
||||
#define CSV_LOG_DIR AST_LOG_DIR "/cdr-csv"
|
||||
#define CSV_MASTER CSV_LOG_DIR "/Master.csv"
|
||||
|
||||
#define DATE_FORMAT "%Y-%m-%d %T"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
|
||||
/* The values are as follows:
|
||||
|
||||
|
||||
"accountcode",
|
||||
"source",
|
||||
"destination",
|
||||
"destination context",
|
||||
"callerid",
|
||||
"channel",
|
||||
"destination channel", (if applicable)
|
||||
"last application",
|
||||
"last app argument",
|
||||
"start time",
|
||||
"answer time",
|
||||
"end time",
|
||||
duration,
|
||||
billable seconds,
|
||||
"disposition",
|
||||
"amaflags",
|
||||
|
||||
*/
|
||||
|
||||
static char *desc = "Comma Separated Values CDR Backend";
|
||||
|
||||
static char *name = "csv";
|
||||
|
||||
static FILE *mf = NULL;
|
||||
|
||||
static int append_string(char *buf, char *s, int len)
|
||||
{
|
||||
int pos = strlen(buf);
|
||||
int spos = 0;
|
||||
int error = 0;
|
||||
if (pos >= len - 4)
|
||||
return -1;
|
||||
buf[pos++] = '\"';
|
||||
error = -1;
|
||||
while(pos < len - 3) {
|
||||
if (!s[spos]) {
|
||||
error = 0;
|
||||
break;
|
||||
}
|
||||
if (s[spos] == '\"')
|
||||
buf[pos++] = '\"';
|
||||
buf[pos++] = s[spos];
|
||||
spos++;
|
||||
}
|
||||
buf[pos++] = '\"';
|
||||
buf[pos++] = ',';
|
||||
buf[pos++] = '\0';
|
||||
return error;
|
||||
}
|
||||
|
||||
static int append_int(char *buf, int s, int len)
|
||||
{
|
||||
char tmp[32];
|
||||
int pos = strlen(buf);
|
||||
snprintf(tmp, sizeof(tmp), "%d", s);
|
||||
if (pos + strlen(tmp) > len - 3)
|
||||
return -1;
|
||||
strncat(buf, tmp, len);
|
||||
pos = strlen(buf);
|
||||
buf[pos++] = ',';
|
||||
buf[pos++] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int append_date(char *buf, struct timeval tv, int len)
|
||||
{
|
||||
char tmp[80];
|
||||
struct tm *tm;
|
||||
time_t t;
|
||||
t = tv.tv_sec;
|
||||
if (strlen(buf) > len - 3)
|
||||
return -1;
|
||||
if (!tv.tv_sec && !tv.tv_usec) {
|
||||
strncat(buf, ",", len);
|
||||
return 0;
|
||||
}
|
||||
tm = localtime(&t);
|
||||
strftime(tmp, sizeof(tmp), DATE_FORMAT, tm);
|
||||
return append_string(buf, tmp, len);
|
||||
}
|
||||
|
||||
static int build_csv_record(char *buf, int len, struct ast_cdr *cdr)
|
||||
{
|
||||
buf[0] = '\0';
|
||||
/* Account code */
|
||||
append_string(buf, cdr->accountcode, len);
|
||||
/* Source */
|
||||
append_string(buf, cdr->src, len);
|
||||
/* Destination */
|
||||
append_string(buf, cdr->dst, len);
|
||||
/* Destination context */
|
||||
append_string(buf, cdr->dcontext, len);
|
||||
/* Caller*ID */
|
||||
append_string(buf, cdr->clid, len);
|
||||
/* Channel */
|
||||
append_string(buf, cdr->channel, len);
|
||||
/* Destination Channel */
|
||||
append_string(buf, cdr->dstchannel, len);
|
||||
/* Last Application */
|
||||
append_string(buf, cdr->lastapp, len);
|
||||
/* Last Data */
|
||||
append_string(buf, cdr->lastdata, len);
|
||||
/* Start Time */
|
||||
append_date(buf, cdr->start, len);
|
||||
/* Answer Time */
|
||||
append_date(buf, cdr->answer, len);
|
||||
/* End Time */
|
||||
append_date(buf, cdr->end, len);
|
||||
/* Duration */
|
||||
append_int(buf, cdr->duration, len);
|
||||
/* Billable seconds */
|
||||
append_int(buf, cdr->billsec, len);
|
||||
/* Disposition */
|
||||
append_string(buf, ast_cdr_disp2str(cdr->disposition), len);
|
||||
/* AMA Flags */
|
||||
append_string(buf, ast_cdr_flags2str(cdr->amaflags), len);
|
||||
|
||||
/* If we hit the end of our buffer, log an error */
|
||||
if (strlen(buf) < len - 5) {
|
||||
/* Trim off trailing comma */
|
||||
buf[strlen(buf) - 1] = '\0';
|
||||
strncat(buf, "\n", len);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int writefile(char *s, char *acc)
|
||||
{
|
||||
char tmp[256];
|
||||
FILE *f;
|
||||
if (strchr(acc, '/') || (acc[0] == '.')) {
|
||||
ast_log(LOG_WARNING, "Account code '%s' insecure for writing file\n", acc);
|
||||
return -1;
|
||||
}
|
||||
snprintf(tmp, sizeof(tmp), "%s/%s.csv", CSV_LOG_DIR, acc);
|
||||
f = fopen(tmp, "a");
|
||||
if (!f)
|
||||
return -1;
|
||||
fputs(s, f);
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int csv_log(struct ast_cdr *cdr)
|
||||
{
|
||||
/* Make sure we have a big enough buf */
|
||||
char buf[1024];
|
||||
#if 0
|
||||
printf("[CDR] %s ('%s' -> '%s') Dur: %ds Bill: %ds Disp: %s Flags: %s Account: [%s]\n", cdr->channel, cdr->src, cdr->dst, cdr->duration, cdr->billsec, ast_cdr_disp2str(cdr->disposition), ast_cdr_flags2str(cdr->amaflags), cdr->accountcode);
|
||||
#endif
|
||||
if (build_csv_record(buf, sizeof(buf), cdr)) {
|
||||
ast_log(LOG_WARNING, "Unable to create CSV record in %d bytes. CDR not recorded!\n", sizeof(buf));
|
||||
} else {
|
||||
/* because of the absolutely unconditional need for the
|
||||
highest reliability possible in writing billing records,
|
||||
we open write and close the log file each time */
|
||||
mf = fopen(CSV_MASTER, "a");
|
||||
if (!mf) {
|
||||
ast_log(LOG_ERROR, "Unable to re-open master file %s\n", CSV_MASTER);
|
||||
}
|
||||
if (mf) {
|
||||
fputs(buf, mf);
|
||||
fflush(mf); /* be particularly anal here */
|
||||
fclose(mf);
|
||||
mf = NULL;
|
||||
}
|
||||
if (strlen(cdr->accountcode)) {
|
||||
if (writefile(buf, cdr->accountcode))
|
||||
ast_log(LOG_WARNING, "Unable to write CSV record to account file '%s'\n", cdr->accountcode);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return desc;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
if (mf)
|
||||
fclose(mf);
|
||||
ast_cdr_unregister(name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_cdr_register(name, desc, csv_log);
|
||||
if (res) {
|
||||
ast_log(LOG_ERROR, "Unable to register CSV CDR handling\n");
|
||||
if (mf)
|
||||
fclose(mf);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int reload(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
240
cdr/cdr_mysql.c
Normal file
240
cdr/cdr_mysql.c
Normal file
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* MySQL CDR logger
|
||||
*
|
||||
* James Sharp <jsharp@psychoses.org>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <asterisk/config.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/cdr.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include "../asterisk.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <mysql.h>
|
||||
|
||||
#define DATE_FORMAT "%Y-%m-%d %T"
|
||||
|
||||
static char *desc = "MySQL CDR Backend";
|
||||
static char *name = "mysql";
|
||||
static char *config = "cdr_mysql.conf";
|
||||
|
||||
static MYSQL *mysql;
|
||||
|
||||
static int mysql_log(struct ast_cdr *cdr)
|
||||
{
|
||||
struct tm *tm;
|
||||
struct timeval *tv;
|
||||
struct timezone *tz;
|
||||
char *sqlcmd, *timestr;
|
||||
time_t t;
|
||||
|
||||
|
||||
tv = (struct timeval *)malloc(sizeof(struct timeval));
|
||||
tz = (struct timezone *)malloc(sizeof(struct timezone));
|
||||
sqlcmd = (char *)malloc(2048);
|
||||
timestr = (char*)malloc(128);
|
||||
memset(sqlcmd,0,2048);
|
||||
|
||||
|
||||
gettimeofday(tv,tz);
|
||||
t = tv->tv_sec;
|
||||
tm = localtime(&t);
|
||||
strftime(timestr,128,DATE_FORMAT,tm);
|
||||
|
||||
|
||||
ast_log(LOG_DEBUG,"cdr_mysql: inserting a CDR record.\n");
|
||||
sprintf(sqlcmd,"insert into cdr values ('%s','%s','%s','%s','%s', '%s','%s','%s','%s',%i,%i,%i,%i,'%s')",timestr,cdr->clid,cdr->src, cdr->dst, cdr->dcontext,cdr->channel, cdr->dstchannel, cdr->lastapp, cdr->lastdata,cdr->duration,cdr->billsec,cdr->disposition,cdr->amaflags, cdr->accountcode);
|
||||
|
||||
ast_log(LOG_DEBUG,"cdr_mysql: SQL command as follows: %s\n",sqlcmd);
|
||||
|
||||
if (mysql_real_query(mysql,sqlcmd,strlen(sqlcmd)))
|
||||
{
|
||||
ast_log(LOG_ERROR,"Failed to insert into database.");
|
||||
free(sqlcmd);
|
||||
return -1;
|
||||
}
|
||||
free(sqlcmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return desc;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
|
||||
mysql_close(mysql);
|
||||
ast_cdr_unregister(name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
int res;
|
||||
struct ast_config *cfg;
|
||||
struct ast_variable *var;
|
||||
|
||||
char *hostname, *dbname, *dbuser, *password;
|
||||
|
||||
cfg = ast_load(config);
|
||||
if (!cfg) {
|
||||
ast_log(LOG_WARNING, "Unable to load config for mysql CDR's: %s\n", config);
|
||||
return 0;
|
||||
}
|
||||
|
||||
var = ast_variable_browse(cfg, "global");
|
||||
if (!var) {
|
||||
/* nothing configured */
|
||||
return 0;
|
||||
}
|
||||
|
||||
hostname = ast_variable_retrieve(cfg,"global","hostname");
|
||||
dbname = ast_variable_retrieve(cfg,"global","dbname");
|
||||
dbuser = ast_variable_retrieve(cfg,"global","user");
|
||||
password = ast_variable_retrieve(cfg,"global","password");
|
||||
ast_log(LOG_DEBUG,"cdr_mysql: got hostname of %s\n",hostname);
|
||||
ast_log(LOG_DEBUG,"cdr_mysql: got user of %s\n",dbuser);
|
||||
ast_log(LOG_DEBUG,"cdr_mysql: got dbname of %s\n",dbname);
|
||||
ast_log(LOG_DEBUG,"cdr_mysql: got password of %s\n",password);
|
||||
|
||||
if (hostname == NULL)
|
||||
{
|
||||
ast_log(LOG_ERROR,"Database server hostname not specified.\n");
|
||||
return -1;
|
||||
}
|
||||
if (dbuser == NULL)
|
||||
{
|
||||
ast_log(LOG_ERROR,"Database dbuser not specified.\n");
|
||||
return -1;
|
||||
}
|
||||
if (dbname == NULL)
|
||||
{
|
||||
ast_log(LOG_ERROR,"Database dbname not specified.\n");
|
||||
return -1;
|
||||
}
|
||||
if (password == NULL)
|
||||
{
|
||||
ast_log(LOG_ERROR,"Database password not specified.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
mysql = mysql_init(NULL);
|
||||
|
||||
mysql = mysql_real_connect(mysql, hostname, dbuser, password, dbname, 0, NULL, 0);
|
||||
|
||||
if (mysql == NULL) {
|
||||
ast_log(LOG_ERROR, "Failed to connect to mysql database.\n");
|
||||
return -1;
|
||||
} else {
|
||||
ast_log(LOG_DEBUG,"Successfully connected to MySQL database.\n");
|
||||
}
|
||||
|
||||
|
||||
res = ast_cdr_register(name, desc, mysql_log);
|
||||
if (res) {
|
||||
ast_log(LOG_ERROR, "Unable to register MySQL CDR handling\n");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int reload(void)
|
||||
{
|
||||
|
||||
struct ast_config *cfg;
|
||||
struct ast_variable *var;
|
||||
|
||||
char *hostname, *dbname, *password, *dbuser;
|
||||
|
||||
mysql_close(mysql);
|
||||
|
||||
|
||||
cfg = ast_load(config);
|
||||
if (!cfg) {
|
||||
ast_log(LOG_WARNING, "Unable to load MySQL CDR config %s\n", config);
|
||||
return 0;
|
||||
}
|
||||
|
||||
var = ast_variable_browse(cfg, "global");
|
||||
if (!var) {
|
||||
/* nothing configured */
|
||||
return 0;
|
||||
}
|
||||
|
||||
hostname = ast_variable_retrieve(cfg,"global","hostname");
|
||||
dbname = ast_variable_retrieve(cfg,"global","dbname");
|
||||
dbuser = ast_variable_retrieve(cfg,"global","user");
|
||||
password = ast_variable_retrieve(cfg,"global","password");
|
||||
ast_log(LOG_DEBUG,"cdr_mysql: got hostname of %s\n",hostname);
|
||||
ast_log(LOG_DEBUG,"cdr_mysql: got dbname of %s\n",dbname);
|
||||
ast_log(LOG_DEBUG,"cdr_mysql: got dbuser of %s\n",dbuser);
|
||||
ast_log(LOG_DEBUG,"cdr_mysql: got password of %s\n",password);
|
||||
|
||||
if (hostname == NULL)
|
||||
{
|
||||
ast_log(LOG_ERROR,"Database server hostname not specified.\n");
|
||||
return -1;
|
||||
}
|
||||
if (dbname == NULL)
|
||||
{
|
||||
ast_log(LOG_ERROR,"Database dbname not specified.\n");
|
||||
return -1;
|
||||
}
|
||||
if (dbuser == NULL)
|
||||
{
|
||||
ast_log(LOG_ERROR,"Database dbuser not specified.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (password == NULL)
|
||||
{
|
||||
ast_log(LOG_ERROR,"Database password not specified.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mysql = mysql_init(NULL);
|
||||
|
||||
mysql = mysql_real_connect(mysql, hostname, dbuser, password, dbname, 0, NULL, 0);
|
||||
|
||||
if (mysql == NULL) {
|
||||
ast_log(LOG_ERROR, "Failed to connect to mysql database.\n");
|
||||
return -1;
|
||||
} else {
|
||||
ast_log(LOG_DEBUG,"Successfully connected to MySQL database.\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
570
channel.c
570
channel.c
@@ -18,7 +18,10 @@
|
||||
#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>
|
||||
#include <asterisk/channel.h>
|
||||
@@ -27,6 +30,7 @@
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/translate.h>
|
||||
|
||||
static int shutting_down = 0;
|
||||
|
||||
/* XXX Lock appropriately in more functions XXX */
|
||||
|
||||
@@ -61,7 +65,70 @@ 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)
|
||||
{
|
||||
time_t myt;
|
||||
|
||||
/* if soft hangup flag, return true */
|
||||
if (chan->softhangup) return 1;
|
||||
/* if no hangup scheduled, just return here */
|
||||
if (!chan->whentohangup) return 0;
|
||||
time(&myt); /* get current time */
|
||||
/* return, if not yet */
|
||||
if (chan->whentohangup > myt) return 0;
|
||||
chan->softhangup = 1;
|
||||
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;
|
||||
|
||||
time(&myt);
|
||||
chan->whentohangup = myt + offset;
|
||||
return;
|
||||
}
|
||||
|
||||
int ast_channel_register(char *type, char *description, int capabilities,
|
||||
struct ast_channel *(*requester)(char *type, int format, void *data))
|
||||
@@ -87,8 +154,8 @@ int ast_channel_register(char *type, char *description, int capabilities,
|
||||
PTHREAD_MUTEX_UNLOCK(&chlock);
|
||||
return -1;
|
||||
}
|
||||
strncpy(chan->type, type, sizeof(chan->type));
|
||||
strncpy(chan->description, description, sizeof(chan->description));
|
||||
strncpy(chan->type, type, sizeof(chan->type)-1);
|
||||
strncpy(chan->description, description, sizeof(chan->description)-1);
|
||||
chan->capabilities = capabilities;
|
||||
chan->requester = requester;
|
||||
chan->next = NULL;
|
||||
@@ -164,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));
|
||||
@@ -178,22 +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));
|
||||
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));
|
||||
strncpy(tmp->language, defaultlanguage, sizeof(tmp->language));
|
||||
strncpy(tmp->exten, "s", sizeof(tmp->exten));
|
||||
tmp->priority=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);
|
||||
@@ -210,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;
|
||||
@@ -245,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) {
|
||||
@@ -276,7 +437,20 @@ void ast_channel_free(struct ast_channel *chan)
|
||||
free(chan->dnid);
|
||||
if (chan->callerid)
|
||||
free(chan->callerid);
|
||||
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);
|
||||
@@ -330,6 +504,18 @@ 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);
|
||||
/* Post and Free the CDR */
|
||||
ast_cdr_post(chan->cdr);
|
||||
ast_cdr_free(chan->cdr);
|
||||
}
|
||||
if (chan->blocking) {
|
||||
ast_log(LOG_WARNING, "Hard hangup called by thread %ld on %s, while fd "
|
||||
"is blocked by thread %ld in procedure %s! Expect a failure\n",
|
||||
@@ -380,7 +566,7 @@ int ast_answer(struct ast_channel *chan)
|
||||
{
|
||||
int res = 0;
|
||||
/* Stop if we're a zombie or need a soft hangup */
|
||||
if (chan->zombie || chan->softhangup)
|
||||
if (chan->zombie || ast_check_hangup(chan))
|
||||
return -1;
|
||||
switch(chan->state) {
|
||||
case AST_STATE_RINGING:
|
||||
@@ -388,6 +574,8 @@ int ast_answer(struct ast_channel *chan)
|
||||
if (chan->pvt->answer)
|
||||
res = chan->pvt->answer(chan);
|
||||
chan->state = AST_STATE_UP;
|
||||
if (chan->cdr)
|
||||
ast_cdr_answer(chan->cdr);
|
||||
return res;
|
||||
break;
|
||||
case AST_STATE_UP:
|
||||
@@ -396,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. */
|
||||
@@ -473,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)
|
||||
@@ -501,8 +713,12 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds,
|
||||
/* Simulate a timeout if we were interrupted */
|
||||
if (errno != EINTR)
|
||||
*ms = -1;
|
||||
else
|
||||
else {
|
||||
/* Just an interrupt */
|
||||
#if 0
|
||||
*ms = 0;
|
||||
#endif
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -557,7 +773,7 @@ char ast_waitfordigit(struct ast_channel *c, int ms)
|
||||
struct ast_frame *f;
|
||||
char result = 0;
|
||||
/* Stop if we're a zombie or need a soft hangup */
|
||||
if (c->zombie || c->softhangup)
|
||||
if (c->zombie || ast_check_hangup(c))
|
||||
return -1;
|
||||
/* Wait for a digit, no more than ms milliseconds total. */
|
||||
while(ms && !result) {
|
||||
@@ -581,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");
|
||||
@@ -598,11 +815,11 @@ struct ast_frame *ast_read(struct ast_channel *chan)
|
||||
}
|
||||
|
||||
/* Stop if we're a zombie or need a soft hangup */
|
||||
if (chan->zombie || chan->softhangup) {
|
||||
if (chan->zombie || ast_check_hangup(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;
|
||||
@@ -613,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);
|
||||
@@ -633,18 +866,41 @@ struct ast_frame *ast_read(struct ast_channel *chan)
|
||||
f = &null_frame;
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure we always return NULL in the future */
|
||||
if (!f)
|
||||
if (!f) {
|
||||
chan->softhangup = 1;
|
||||
else if (chan->deferdtmf && f->frametype == AST_FRAME_DTMF) {
|
||||
/* End the CDR if appropriate */
|
||||
if (chan->cdr)
|
||||
ast_cdr_end(chan->cdr);
|
||||
} else if (chan->deferdtmf && f->frametype == AST_FRAME_DTMF) {
|
||||
if (strlen(chan->dtmfq) < sizeof(chan->dtmfq) - 2)
|
||||
chan->dtmfq[strlen(chan->dtmfq)] = f->subclass;
|
||||
else
|
||||
ast_log(LOG_WARNING, "Dropping deferred DTMF digits on %s\n", chan->name);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -652,7 +908,7 @@ int ast_indicate(struct ast_channel *chan, int condition)
|
||||
{
|
||||
int res = -1;
|
||||
/* Stop if we're a zombie or need a soft hangup */
|
||||
if (chan->zombie || chan->softhangup)
|
||||
if (chan->zombie || ast_check_hangup(chan))
|
||||
return -1;
|
||||
if (chan->pvt->indicate) {
|
||||
res = chan->pvt->indicate(chan, condition);
|
||||
@@ -663,11 +919,40 @@ int ast_indicate(struct ast_channel *chan, int condition)
|
||||
return res;
|
||||
}
|
||||
|
||||
int ast_recvchar(struct ast_channel *chan, int timeout)
|
||||
{
|
||||
int res,ourto,c;
|
||||
struct ast_frame *f;
|
||||
|
||||
ourto = timeout;
|
||||
for(;;)
|
||||
{
|
||||
if (ast_check_hangup(chan)) return -1;
|
||||
res = ast_waitfor(chan,ourto);
|
||||
if (res <= 0) /* if timeout */
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
ourto = res;
|
||||
f = ast_read(chan);
|
||||
if (f == NULL) return -1; /* if hangup */
|
||||
if ((f->frametype == AST_FRAME_CONTROL) &&
|
||||
(f->subclass == AST_CONTROL_HANGUP)) return -1; /* if hangup */
|
||||
if (f->frametype == AST_FRAME_TEXT) /* if a text frame */
|
||||
{
|
||||
c = *((char *)f->data); /* get the data */
|
||||
ast_frfree(f);
|
||||
return(c);
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
}
|
||||
|
||||
int ast_sendtext(struct ast_channel *chan, char *text)
|
||||
{
|
||||
int res = 0;
|
||||
/* Stop if we're a zombie or need a soft hangup */
|
||||
if (chan->zombie || chan->softhangup)
|
||||
if (chan->zombie || ast_check_hangup(chan))
|
||||
return -1;
|
||||
CHECK_BLOCKING(chan);
|
||||
if (chan->pvt->send_text)
|
||||
@@ -681,7 +966,7 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
|
||||
int res = -1;
|
||||
struct ast_frame *f;
|
||||
/* Stop if we're a zombie or need a soft hangup */
|
||||
if (chan->zombie || chan->softhangup)
|
||||
if (chan->zombie || ast_check_hangup(chan))
|
||||
return -1;
|
||||
/* Handle any pending masquerades */
|
||||
if (chan->masq) {
|
||||
@@ -692,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:
|
||||
@@ -699,10 +990,13 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
|
||||
ast_log(LOG_WARNING, "Don't know how to handle control frames yet\n");
|
||||
break;
|
||||
case AST_FRAME_DTMF:
|
||||
|
||||
if (chan->pvt->send_digit)
|
||||
res = chan->pvt->send_digit(chan, fr->subclass);
|
||||
break;
|
||||
case AST_FRAME_TEXT:
|
||||
if (chan->pvt->send_text)
|
||||
res = chan->pvt->send_text(chan, (char *) fr->data);
|
||||
break;
|
||||
default:
|
||||
if (chan->pvt->write) {
|
||||
if (chan->pvt->writetrans) {
|
||||
@@ -716,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;
|
||||
}
|
||||
|
||||
@@ -744,7 +1041,7 @@ int ast_set_write_format(struct ast_channel *chan, int fmts)
|
||||
/* Build a translation path from the user write format to the raw writing format */
|
||||
chan->pvt->writetrans = ast_translator_build_path(chan->pvt->rawwriteformat, chan->writeformat);
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "Set channel %s to format %d\n", chan->name, chan->writeformat);
|
||||
ast_log(LOG_DEBUG, "Set channel %s to write format %d\n", chan->name, chan->writeformat);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -772,6 +1069,8 @@ int ast_set_read_format(struct ast_channel *chan, int fmts)
|
||||
ast_translator_free_path(chan->pvt->readtrans);
|
||||
/* Build a translation path from the raw read format to the user reading format */
|
||||
chan->pvt->readtrans = ast_translator_build_path(chan->readformat, chan->pvt->rawreadformat);
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "Set channel %s to read format %d\n", chan->name, chan->readformat);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -817,8 +1116,8 @@ 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);
|
||||
if (!chan->zombie && !chan->softhangup)
|
||||
ast_pthread_mutex_lock(&chan->lock);
|
||||
if (!chan->zombie && !ast_check_hangup(chan))
|
||||
if (chan->pvt->call)
|
||||
res = chan->pvt->call(chan, addr, timeout);
|
||||
pthread_mutex_unlock(&chan->lock);
|
||||
@@ -831,7 +1130,7 @@ int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int fti
|
||||
int to = ftimeout;
|
||||
char d;
|
||||
/* Stop if we're a zombie or need a soft hangup */
|
||||
if (c->zombie || c->softhangup)
|
||||
if (c->zombie || ast_check_hangup(c))
|
||||
return -1;
|
||||
if (!len)
|
||||
return -1;
|
||||
@@ -853,7 +1152,7 @@ int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int fti
|
||||
}
|
||||
if (!strchr(enders, d))
|
||||
s[pos++] = d;
|
||||
if (strchr(enders, d) || (pos >= len - 1)) {
|
||||
if (strchr(enders, d) || (pos >= len)) {
|
||||
s[pos]='\0';
|
||||
return 0;
|
||||
}
|
||||
@@ -893,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 */
|
||||
@@ -913,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;
|
||||
@@ -975,14 +1274,14 @@ 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;
|
||||
clone->masqr = NULL;
|
||||
|
||||
/* Copy the name from the clone channel */
|
||||
strncpy(original->name, clone->name, sizeof(original->name));
|
||||
strncpy(original->name, clone->name, sizeof(original->name)-1);
|
||||
|
||||
/* Mangle the name of the clone channel */
|
||||
strncat(clone->name, "<MASQ>", sizeof(clone->name));
|
||||
@@ -1019,6 +1318,8 @@ static int ast_do_masquerade(struct ast_channel *original)
|
||||
/* Copy the FD's */
|
||||
for (x=0;x<AST_MAX_FDS;x++)
|
||||
original->fds[x] = clone->fds[x];
|
||||
/* Presense of ADSI capable CPE follows clone */
|
||||
original->adsicpe = clone->adsicpe;
|
||||
/* Bridge remains the same */
|
||||
/* CDR fields remain the same */
|
||||
/* XXX What about blocking, softhangup, blocker, and lock and blockproc? XXX */
|
||||
@@ -1096,7 +1397,7 @@ int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags
|
||||
int res;
|
||||
int nativefailed=0;
|
||||
/* Stop if we're a zombie or need a soft hangup */
|
||||
if (c0->zombie || c0->softhangup || c1->zombie || c1->softhangup)
|
||||
if (c0->zombie || ast_check_hangup(c0) || c1->zombie || ast_check_hangup(c1))
|
||||
return -1;
|
||||
if (c0->bridge) {
|
||||
ast_log(LOG_WARNING, "%s is already in a bridge with %s\n",
|
||||
@@ -1116,7 +1417,7 @@ int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags
|
||||
cs[1] = c1;
|
||||
for (/* ever */;;) {
|
||||
/* Stop if we're a zombie or need a soft hangup */
|
||||
if (c0->zombie || c0->softhangup || c1->zombie || c1->softhangup) {
|
||||
if (c0->zombie || ast_check_hangup(c0) || c1->zombie || ast_check_hangup(c1)) {
|
||||
*fo = NULL;
|
||||
if (who) *rc = who;
|
||||
res = 0;
|
||||
@@ -1125,6 +1426,8 @@ int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags
|
||||
if (c0->pvt->bridge &&
|
||||
(c0->pvt->bridge == c1->pvt->bridge) && !nativefailed) {
|
||||
/* Looks like they share a bridge code */
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Attempting native bridge of %s and %s\n", c0->name, c1->name);
|
||||
if (!(res = c0->pvt->bridge(c0, c1, flags, fo, rc))) {
|
||||
c0->bridge = NULL;
|
||||
c1->bridge = NULL;
|
||||
@@ -1138,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;
|
||||
@@ -1196,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
|
||||
@@ -1233,3 +1541,137 @@ 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;
|
||||
}
|
||||
|
||||
@@ -11,17 +11,29 @@
|
||||
# the GNU General Public License
|
||||
#
|
||||
|
||||
CHANNEL_LIBS=chan_vofr.so chan_modem.so \
|
||||
chan_modem_aopen.so chan_iax.so chan_oss.so \
|
||||
CHANNEL_LIBS=chan_modem.so chan_iax.so chan_sip.so \
|
||||
chan_modem_aopen.so chan_oss.so \
|
||||
chan_modem_bestdata.so chan_modem_i4l.so
|
||||
|
||||
#
|
||||
# If you really want VoFR you can have it :-P
|
||||
#
|
||||
#CHANNEL_LIBS+=chan_vofr
|
||||
|
||||
CHANNEL_LIBS+=$(shell [ -f /usr/include/linux/ixjuser.h ] && echo chan_phone.so)
|
||||
|
||||
CFLAGS+=-Wno-missing-prototypes -Wno-missing-declarations
|
||||
CFLAGS+=$(shell [ ! -f /usr/include/linux/if_wanpipe.h ] && echo " -DOLD_SANGOMA_API")
|
||||
CHANNEL_LIBS+=$(shell [ -f /usr/include/alsa/asoundlib.h ] && echo "chan_alsa.so")
|
||||
CFLAGS+=$(shell [ -f /usr/lib/libpri.so.1 ] && echo " -DZAPATA_PRI")
|
||||
CFLAGS+=$(shell [ -f alsa-monitor.h ] && echo " -DALSA_MONITOR")
|
||||
ZAPPRI=$(shell [ -f /usr/lib/libpri.so.1 ] && echo "-lpri")
|
||||
|
||||
ALSA_SRC=chan_alsa.c
|
||||
ALSA_SRC+=$(shell [ -f alsa-monitor.h ] && echo "alsa-monitor.h")
|
||||
|
||||
CFLAGS+=-DCRYPTO
|
||||
|
||||
CFLAGS+=#-DVOFRDUMPER
|
||||
|
||||
ZAPDIR=/usr/lib
|
||||
@@ -30,11 +42,11 @@ CHANNEL_LIBS+=$(shell [ -f $(ZAPDIR)/libzap.a ] && echo "chan_zap.so")
|
||||
|
||||
CFLAGS+=$(shell [ -f $(ZAPDIR)/libzap.a ] && echo "-I$(ZAPDIR)")
|
||||
|
||||
all: $(CHANNEL_LIBS)
|
||||
all: $(CHANNEL_LIBS)
|
||||
|
||||
clean:
|
||||
rm -f *.so *.o
|
||||
rm -f busy.h ringtone.h gentone
|
||||
rm -f busy.h ringtone.h gentone gentone-ulaw
|
||||
|
||||
%.so : %.o
|
||||
$(CC) -shared -Xlinker -x -o $@ $<
|
||||
@@ -42,6 +54,9 @@ clean:
|
||||
gentone: gentone.c
|
||||
$(CC) -o gentone gentone.c -lm
|
||||
|
||||
gentone-ulaw: gentone-ulaw.c
|
||||
$(CC) -o gentone-ulaw gentone-ulaw.c -lm
|
||||
|
||||
busy.h: gentone
|
||||
./gentone busy 480 620
|
||||
|
||||
@@ -53,6 +68,11 @@ chan_oss.o: chan_oss.c busy.h ringtone.h
|
||||
chan_zap.so: chan_zap.o
|
||||
$(CC) -shared -Xlinker -x -o $@ $< $(ZAPPRI) -lzap -ltonezone
|
||||
|
||||
chan_alsa.o: $(ALSA_SRC)
|
||||
|
||||
chan_alsa.so: chan_alsa.o
|
||||
$(CC) -shared -Xlinker -x -o $@ $< -lasound -lm -ldl
|
||||
|
||||
#chan_modem.so : chan_modem.o
|
||||
# $(CC) -rdynamic -shared -Xlinker -x -o $@ $<
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
1113
channels/chan_alsa.c
Normal file
1113
channels/chan_alsa.c
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -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>
|
||||
@@ -64,14 +65,14 @@ static int baudrate = 115200;
|
||||
|
||||
static int stripmsd = 0;
|
||||
|
||||
static pthread_mutex_t usecnt_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t usecnt_lock = AST_MUTEX_INITIALIZER;
|
||||
|
||||
/* Protect the interface list (of ast_modem_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. */
|
||||
@@ -90,7 +91,7 @@ static int modem_digit(struct ast_channel *ast, char digit)
|
||||
p = ast->pvt->pvt;
|
||||
if (p->mc->dialdigit)
|
||||
return p->mc->dialdigit(p, digit);
|
||||
else ast_log(LOG_DEBUG, "Channel %s lacks digit dialing\n");
|
||||
else ast_log(LOG_DEBUG, "Channel %s lacks digit dialing\n", ast->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -165,7 +166,7 @@ static int modem_call(struct ast_channel *ast, char *idest, int timeout)
|
||||
struct ast_modem_pvt *p;
|
||||
int ms = timeout;
|
||||
char rdest[80], *where, dstr[100];
|
||||
strncpy(rdest, idest, sizeof(rdest));
|
||||
strncpy(rdest, idest, sizeof(rdest)-1);
|
||||
strtok(rdest, ":");
|
||||
where = strtok(NULL, ":");
|
||||
if (!where) {
|
||||
@@ -245,7 +246,7 @@ int ast_modem_read_response(struct ast_modem_pvt *p, int timeout)
|
||||
do {
|
||||
res = ast_waitfor_n_fd(&p->fd, 1, &timeout, NULL);
|
||||
if (res < 0) {
|
||||
strncpy(p->response, "(No Response)", sizeof(p->response));
|
||||
strncpy(p->response, "(No Response)", sizeof(p->response)-1);
|
||||
return -1;
|
||||
}
|
||||
/* get no more then buffer length */
|
||||
@@ -257,7 +258,7 @@ int ast_modem_read_response(struct ast_modem_pvt *p, int timeout)
|
||||
/* if nothing in buffer, go back into timeout stuff */
|
||||
if (errno == EWOULDBLOCK) break;
|
||||
/* return as error */
|
||||
strncpy(p->response, "(No Response)", sizeof(p->response));
|
||||
strncpy(p->response, "(No Response)", sizeof(p->response)-1);
|
||||
return -1;
|
||||
}
|
||||
/* save char */
|
||||
@@ -281,7 +282,7 @@ int ast_modem_read_response(struct ast_modem_pvt *p, int timeout)
|
||||
}
|
||||
}
|
||||
} while(timeout > 0);
|
||||
strncpy(p->response, "(No Response)", sizeof(p->response));
|
||||
strncpy(p->response, "(No Response)", sizeof(p->response)-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -289,7 +290,7 @@ int ast_modem_expect(struct ast_modem_pvt *p, char *result, int timeout)
|
||||
{
|
||||
int res = -1;
|
||||
timeout *= 1000;
|
||||
strncpy(p->response, "(No Response)", sizeof(p->response));
|
||||
strncpy(p->response, "(No Response)", sizeof(p->response)-1);
|
||||
do {
|
||||
res = ast_waitfor_n_fd(&p->fd, 1, &timeout, NULL);
|
||||
if (res < 0) {
|
||||
@@ -363,7 +364,7 @@ static int modem_setup(struct ast_modem_pvt *p, int baudrate)
|
||||
ast_log(LOG_WARNING, "Modem did not provide identification\n");
|
||||
return -1;
|
||||
}
|
||||
strncpy(identity, p->response, sizeof(identity));
|
||||
strncpy(identity, p->response, sizeof(identity)-1);
|
||||
ast_modem_trim(identity);
|
||||
if (ast_modem_expect(p, "OK", ECHO_TIMEOUT)) {
|
||||
ast_log(LOG_WARNING, "Modem did not provide identification\n");
|
||||
@@ -411,6 +412,7 @@ static int modem_hangup(struct ast_channel *ast)
|
||||
p->mc->init(p);
|
||||
ast->state = AST_STATE_DOWN;
|
||||
memset(p->cid, 0, sizeof(p->cid));
|
||||
memset(p->dnid, 0, sizeof(p->dnid));
|
||||
((struct ast_modem_pvt *)(ast->pvt->pvt))->owner = NULL;
|
||||
ast_pthread_mutex_lock(&usecnt_lock);
|
||||
usecnt--;
|
||||
@@ -468,16 +470,25 @@ static struct ast_frame *modem_read(struct ast_channel *ast)
|
||||
static int modem_write(struct ast_channel *ast, struct ast_frame *frame)
|
||||
{
|
||||
int res=0;
|
||||
long flags;
|
||||
struct ast_modem_pvt *p = ast->pvt->pvt;
|
||||
|
||||
/* Temporarily make non-blocking */
|
||||
flags = fcntl(ast->fds[0], F_GETFL);
|
||||
fcntl(ast->fds[0], F_SETFL, flags | O_NONBLOCK);
|
||||
|
||||
if (p->mc->write)
|
||||
res = p->mc->write(p, frame);
|
||||
|
||||
/* Block again */
|
||||
fcntl(ast->fds[0], F_SETFL, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ast_channel *ast_modem_new(struct ast_modem_pvt *i, int state)
|
||||
{
|
||||
struct ast_channel *tmp;
|
||||
tmp = ast_channel_alloc();
|
||||
tmp = ast_channel_alloc(1);
|
||||
if (tmp) {
|
||||
snprintf(tmp->name, sizeof(tmp->name), "Modem[%s]/%s", i->mc->name, i->dev + 5);
|
||||
tmp->type = type;
|
||||
@@ -493,11 +504,13 @@ struct ast_channel *ast_modem_new(struct ast_modem_pvt *i, int state)
|
||||
tmp->pvt->answer = modem_answer;
|
||||
tmp->pvt->read = modem_read;
|
||||
tmp->pvt->write = modem_write;
|
||||
strncpy(tmp->context, i->context, sizeof(tmp->context));
|
||||
strncpy(tmp->context, i->context, sizeof(tmp->context)-1);
|
||||
if (strlen(i->cid))
|
||||
tmp->callerid = strdup(i->cid);
|
||||
if (strlen(i->language))
|
||||
strncpy(tmp->language,i->language, sizeof(tmp->language));
|
||||
strncpy(tmp->language,i->language, sizeof(tmp->language)-1);
|
||||
if (strlen(i->dnid))
|
||||
strncpy(tmp->exten, i->dnid, sizeof(tmp->exten) - 1);
|
||||
i->owner = tmp;
|
||||
ast_pthread_mutex_lock(&usecnt_lock);
|
||||
usecnt++;
|
||||
@@ -677,9 +690,9 @@ static struct ast_modem_pvt *mkif(char *iface)
|
||||
free(tmp);
|
||||
return NULL;
|
||||
}
|
||||
strncpy(tmp->language, language, sizeof(tmp->language));
|
||||
strncpy(tmp->msn, msn, sizeof(tmp->msn));
|
||||
strncpy(tmp->dev, iface, sizeof(tmp->dev));
|
||||
strncpy(tmp->language, language, sizeof(tmp->language)-1);
|
||||
strncpy(tmp->msn, msn, sizeof(tmp->msn)-1);
|
||||
strncpy(tmp->dev, iface, sizeof(tmp->dev)-1);
|
||||
/* Maybe in the future we want to allow variable
|
||||
serial settings */
|
||||
stty(tmp);
|
||||
@@ -691,18 +704,14 @@ static struct ast_modem_pvt *mkif(char *iface)
|
||||
free(tmp);
|
||||
return NULL;
|
||||
}
|
||||
#if 0
|
||||
flags = fcntl(tmp->fd, F_GETFL);
|
||||
fcntl(tmp->fd, F_SETFL, flags | O_NONBLOCK);
|
||||
#endif
|
||||
tmp->owner = NULL;
|
||||
tmp->ministate = 0;
|
||||
tmp->stripmsd = stripmsd;
|
||||
tmp->dialtype = dialtype;
|
||||
tmp->mode = gmode;
|
||||
memset(tmp->cid, 0, sizeof(tmp->cid));
|
||||
strncpy(tmp->context, context, sizeof(tmp->context));
|
||||
strncpy(tmp->initstr, initstr, sizeof(tmp->initstr));
|
||||
strncpy(tmp->context, context, sizeof(tmp->context)-1);
|
||||
strncpy(tmp->initstr, initstr, sizeof(tmp->initstr)-1);
|
||||
tmp->next = NULL;
|
||||
tmp->obuflen = 0;
|
||||
|
||||
@@ -721,7 +730,7 @@ static struct ast_channel *modem_request(char *type, int format, void *data)
|
||||
struct ast_modem_pvt *p;
|
||||
struct ast_channel *tmp = NULL;
|
||||
char dev[80];
|
||||
strncpy(dev, (char *)data, sizeof(dev));
|
||||
strncpy(dev, (char *)data, sizeof(dev)-1);
|
||||
strtok(dev, ":");
|
||||
oldformat = format;
|
||||
/* Search for an unowned channel */
|
||||
@@ -746,7 +755,7 @@ static struct ast_channel *modem_request(char *type, int format, void *data)
|
||||
p = p->next;
|
||||
}
|
||||
if (!p)
|
||||
ast_log(LOG_WARNING, "Requested device '%s' does not exist\n", p->dev);
|
||||
ast_log(LOG_WARNING, "Requested device '%s' does not exist\n", dev);
|
||||
|
||||
ast_pthread_mutex_unlock(&iflock);
|
||||
return tmp;
|
||||
@@ -811,17 +820,17 @@ int load_module()
|
||||
} else if (!strcasecmp(v->name, "stripmsd")) {
|
||||
stripmsd = atoi(v->value);
|
||||
} else if (!strcasecmp(v->name, "type")) {
|
||||
strncpy(mtype, v->value, sizeof(mtype));
|
||||
strncpy(mtype, v->value, sizeof(mtype)-1);
|
||||
} else if (!strcasecmp(v->name, "initstr")) {
|
||||
strncpy(initstr, v->value, sizeof(initstr));
|
||||
strncpy(initstr, v->value, sizeof(initstr)-1);
|
||||
} else if (!strcasecmp(v->name, "dialtype")) {
|
||||
dialtype = toupper(v->value[0]);
|
||||
} else if (!strcasecmp(v->name, "context")) {
|
||||
strncpy(context, v->value, sizeof(context));
|
||||
strncpy(context, v->value, sizeof(context)-1);
|
||||
} else if (!strcasecmp(v->name, "msn")) {
|
||||
strncpy(msn, v->value, sizeof(msn));
|
||||
strncpy(msn, v->value, sizeof(msn)-1);
|
||||
} else if (!strcasecmp(v->name, "language")) {
|
||||
strncpy(language, v->value, sizeof(language));
|
||||
strncpy(language, v->value, sizeof(language)-1);
|
||||
}
|
||||
v = v->next;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/vmodem.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/frame.h>
|
||||
@@ -34,7 +34,7 @@ static char *breakcmd = "\0x10\0x03";
|
||||
static char *desc = "A/Open (Rockwell Chipset) ITU-2 VoiceModem Driver";
|
||||
|
||||
int usecnt;
|
||||
pthread_mutex_t usecnt_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
pthread_mutex_t usecnt_lock = AST_MUTEX_INITIALIZER;
|
||||
|
||||
static char *aopen_idents[] = {
|
||||
/* Identify A/Open Modem */
|
||||
@@ -54,7 +54,7 @@ static int aopen_setdev(struct ast_modem_pvt *p, int dev)
|
||||
return -1;
|
||||
}
|
||||
ast_modem_trim(p->response);
|
||||
strncpy(cmd, p->response, sizeof(cmd));
|
||||
strncpy(cmd, p->response, sizeof(cmd)-1);
|
||||
if (ast_modem_expect(p, "OK", 5)) {
|
||||
ast_log(LOG_WARNING, "Modem did not respond properly\n");
|
||||
return -1;
|
||||
@@ -344,17 +344,17 @@ static char *aopen_identify(struct ast_modem_pvt *p)
|
||||
char rev[80];
|
||||
ast_modem_send(p, "AT#MDL?", 0);
|
||||
ast_modem_read_response(p, 5);
|
||||
strncpy(mdl, p->response, sizeof(mdl));
|
||||
strncpy(mdl, p->response, sizeof(mdl)-1);
|
||||
ast_modem_trim(mdl);
|
||||
ast_modem_expect(p, "OK", 5);
|
||||
ast_modem_send(p, "AT#MFR?", 0);
|
||||
ast_modem_read_response(p, 5);
|
||||
strncpy(mfr, p->response, sizeof(mfr));
|
||||
strncpy(mfr, p->response, sizeof(mfr)-1);
|
||||
ast_modem_trim(mfr);
|
||||
ast_modem_expect(p, "OK", 5);
|
||||
ast_modem_send(p, "AT#REV?", 0);
|
||||
ast_modem_read_response(p, 5);
|
||||
strncpy(rev, p->response, sizeof(rev));
|
||||
strncpy(rev, p->response, sizeof(rev)-1);
|
||||
ast_modem_trim(rev);
|
||||
ast_modem_expect(p, "OK", 5);
|
||||
snprintf(identity, sizeof(identity), "%s Model %s Revision %s", mfr, mdl, rev);
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/vmodem.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/frame.h>
|
||||
@@ -38,7 +38,7 @@ static char *breakcmd = "\020!";
|
||||
static char *desc = "BestData (Conexant V.90 Chipset) VoiceModem Driver";
|
||||
|
||||
int usecnt;
|
||||
pthread_mutex_t usecnt_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
pthread_mutex_t usecnt_lock = AST_MUTEX_INITIALIZER;
|
||||
|
||||
static char *bestdata_idents[] = {
|
||||
/* Identify BestData Modem */
|
||||
@@ -189,7 +189,7 @@ static struct ast_frame *bestdata_handle_escape(struct ast_modem_pvt *p, char es
|
||||
char res[1000];
|
||||
|
||||
if (ast_modem_read_response(p, 5)) break;
|
||||
strncpy(res, p->response, sizeof(res));
|
||||
strncpy(res, p->response, sizeof(res)-1);
|
||||
ast_modem_trim(res);
|
||||
if (!strncmp(res,"\020.",2)) break;
|
||||
if (!strncmp(res,"NAME",4)) strcpy(name,res + 7);
|
||||
@@ -419,17 +419,17 @@ static char *bestdata_identify(struct ast_modem_pvt *p)
|
||||
char rev[80];
|
||||
ast_modem_send(p, "AT+FMM", 0);
|
||||
ast_modem_read_response(p, 5);
|
||||
strncpy(mdl, p->response, sizeof(mdl));
|
||||
strncpy(mdl, p->response, sizeof(mdl)-1);
|
||||
ast_modem_trim(mdl);
|
||||
ast_modem_expect(p, "OK", 5);
|
||||
ast_modem_send(p, "AT+FMI", 0);
|
||||
ast_modem_read_response(p, 5);
|
||||
strncpy(mfr, p->response, sizeof(mfr));
|
||||
strncpy(mfr, p->response, sizeof(mfr)-1);
|
||||
ast_modem_trim(mfr);
|
||||
ast_modem_expect(p, "OK", 5);
|
||||
ast_modem_send(p, "AT+FMR", 0);
|
||||
ast_modem_read_response(p, 5);
|
||||
strncpy(rev, p->response, sizeof(rev));
|
||||
strncpy(rev, p->response, sizeof(rev)-1);
|
||||
ast_modem_trim(rev);
|
||||
ast_modem_expect(p, "OK", 5);
|
||||
snprintf(identity, sizeof(identity), "%s Model %s Revision %s", mfr, mdl, rev);
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/vmodem.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/frame.h>
|
||||
@@ -33,7 +33,7 @@ static char *breakcmd = "\0x10\0x14\0x10\0x3";
|
||||
static char *desc = "ISDN4Linux Emulated Modem Driver";
|
||||
|
||||
int usecnt;
|
||||
pthread_mutex_t usecnt_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
pthread_mutex_t usecnt_lock = AST_MUTEX_INITIALIZER;
|
||||
|
||||
static char *i4l_idents[] = {
|
||||
/* Identify ISDN4Linux Driver */
|
||||
@@ -58,7 +58,7 @@ static int i4l_setdev(struct ast_modem_pvt *p, int dev)
|
||||
return -1;
|
||||
}
|
||||
ast_modem_trim(p->response);
|
||||
strncpy(cmd, p->response, sizeof(cmd));
|
||||
strncpy(cmd, p->response, sizeof(cmd)-1);
|
||||
if (ast_modem_expect(p, "OK", 5)) {
|
||||
ast_log(LOG_WARNING, "Modem did not respond properly\n");
|
||||
return -1;
|
||||
@@ -161,9 +161,9 @@ static int i4l_init(struct ast_modem_pvt *p)
|
||||
ast_log(LOG_WARNING, "Unable to set to transparent mode\n");
|
||||
return -1;
|
||||
}
|
||||
if (ast_modem_send(p, "ATS23=1", 0) ||
|
||||
if (ast_modem_send(p, "ATS23=9", 0) ||
|
||||
ast_modem_expect(p, "OK", 5)) {
|
||||
ast_log(LOG_WARNING, "Unable to set to transparent mode\n");
|
||||
ast_log(LOG_WARNING, "Unable to set to transparent/ringing mode\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -200,6 +200,10 @@ static struct ast_frame *i4l_handle_escape(struct ast_modem_pvt *p, char esc)
|
||||
p->fr.frametype = AST_FRAME_CONTROL;
|
||||
p->fr.subclass = AST_CONTROL_RING;
|
||||
return &p->fr;
|
||||
case 'I': /* Pseudo ringing */
|
||||
p->fr.frametype = AST_FRAME_CONTROL;
|
||||
p->fr.subclass = AST_CONTROL_RINGING;
|
||||
return &p->fr;
|
||||
case 'X': /* Pseudo connect */
|
||||
p->fr.frametype = AST_FRAME_CONTROL;
|
||||
p->fr.subclass = AST_CONTROL_ANSWER;
|
||||
@@ -287,12 +291,17 @@ static struct ast_frame *i4l_read(struct ast_modem_pvt *p)
|
||||
return i4l_handle_escape(p, 'b');
|
||||
} else
|
||||
if (!strncasecmp(result, "CALLER NUMBER: ", 15 )) {
|
||||
strncpy(p->cid, result + 15, sizeof(p->cid));
|
||||
strncpy(p->cid, result + 15, sizeof(p->cid)-1);
|
||||
return i4l_handle_escape(p, 'R');
|
||||
} else
|
||||
if (!strcasecmp(result, "RINGING")) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "%s is ringing...\n", p->dev);
|
||||
return i4l_handle_escape(p, 'I');
|
||||
} else
|
||||
if (!strncasecmp(result, "RING", 4)) {
|
||||
if (result[4]=='/')
|
||||
strncpy(p->dnid, result + 4, sizeof(p->dnid));
|
||||
strncpy(p->dnid, result + 4, sizeof(p->dnid)-1);
|
||||
return i4l_handle_escape(p, 'R');
|
||||
} else
|
||||
if (!strcasecmp(result, "NO CARRIER")) {
|
||||
@@ -377,7 +386,7 @@ static struct ast_frame *i4l_read(struct ast_modem_pvt *p)
|
||||
|
||||
static int i4l_write(struct ast_modem_pvt *p, struct ast_frame *f)
|
||||
{
|
||||
#define MAX_WRITE_SIZE 512
|
||||
#define MAX_WRITE_SIZE 1024
|
||||
unsigned char result[MAX_WRITE_SIZE << 1];
|
||||
unsigned char b;
|
||||
int bpos=0, x;
|
||||
@@ -407,8 +416,10 @@ static int i4l_write(struct ast_modem_pvt *p, struct ast_frame *f)
|
||||
res = write(p->fd, result, bpos);
|
||||
#endif
|
||||
if (res < 1) {
|
||||
ast_log(LOG_WARNING, "Failed to write buffer\n");
|
||||
return -1;
|
||||
if (errno != EAGAIN) {
|
||||
ast_log(LOG_WARNING, "Failed to write buffer\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
printf("Result of write is %d\n", res);
|
||||
@@ -439,7 +450,7 @@ static void i4l_decusecnt()
|
||||
|
||||
static int i4l_answer(struct ast_modem_pvt *p)
|
||||
{
|
||||
if (ast_modem_send(p, "ATA", 0) ||
|
||||
if (ast_modem_send(p, "ATA\r", 4) ||
|
||||
ast_modem_expect(p, "VCON", 10)) {
|
||||
ast_log(LOG_WARNING, "Unable to answer: %s", p->response);
|
||||
return -1;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/frame.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
@@ -55,16 +56,11 @@
|
||||
static struct timeval lasttime;
|
||||
|
||||
static int usecnt;
|
||||
static int needanswer = 0;
|
||||
static int needringing = 0;
|
||||
static int needhangup = 0;
|
||||
static int silencesuppression = 0;
|
||||
static int silencethreshold = 1000;
|
||||
|
||||
static char digits[80] = "";
|
||||
static char text2send[80] = "";
|
||||
|
||||
static pthread_mutex_t usecnt_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t usecnt_lock = AST_MUTEX_INITIALIZER;
|
||||
|
||||
static char *type = "Console";
|
||||
static char *desc = "OSS Console Channel Driver";
|
||||
@@ -75,9 +71,6 @@ static char context[AST_MAX_EXTENSION] = "default";
|
||||
static char language[MAX_LANGUAGE] = "";
|
||||
static char exten[AST_MAX_EXTENSION] = "s";
|
||||
|
||||
/* Command pipe */
|
||||
static int cmd[2];
|
||||
|
||||
int hookstate=0;
|
||||
|
||||
static short silence[FRAME_SIZE] = {0, };
|
||||
@@ -433,13 +426,18 @@ static int oss_text(struct ast_channel *c, char *text)
|
||||
static int oss_call(struct ast_channel *c, char *dest, int timeout)
|
||||
{
|
||||
int res = 3;
|
||||
struct ast_frame f = { 0, };
|
||||
ast_verbose( " << Call placed to '%s' on console >> \n", dest);
|
||||
if (autoanswer) {
|
||||
ast_verbose( " << Auto-answered >> \n" );
|
||||
needanswer = 1;
|
||||
f.frametype = AST_FRAME_CONTROL;
|
||||
f.subclass = AST_CONTROL_ANSWER;
|
||||
ast_queue_frame(c, &f, 0);
|
||||
} else {
|
||||
ast_verbose( " << Type 'answer' to answer, or use 'autoanswer' for future calls >> \n");
|
||||
needringing = 1;
|
||||
f.frametype = AST_FRAME_CONTROL;
|
||||
f.subclass = AST_CONTROL_RINGING;
|
||||
ast_queue_frame(c, &f, 0);
|
||||
write(sndcmd[1], &res, sizeof(res));
|
||||
}
|
||||
return 0;
|
||||
@@ -465,7 +463,7 @@ static int oss_answer(struct ast_channel *c)
|
||||
|
||||
static int oss_hangup(struct ast_channel *c)
|
||||
{
|
||||
int res;
|
||||
int res = 0;
|
||||
cursound = -1;
|
||||
c->pvt->pvt = NULL;
|
||||
oss.owner = NULL;
|
||||
@@ -473,11 +471,15 @@ static int oss_hangup(struct ast_channel *c)
|
||||
ast_pthread_mutex_lock(&usecnt_lock);
|
||||
usecnt--;
|
||||
ast_pthread_mutex_unlock(&usecnt_lock);
|
||||
needhangup = 0;
|
||||
needanswer = 0;
|
||||
if (hookstate) {
|
||||
res = 2;
|
||||
write(sndcmd[1], &res, sizeof(res));
|
||||
if (autoanswer) {
|
||||
/* Assume auto-hangup too */
|
||||
hookstate = 0;
|
||||
} else {
|
||||
/* Make congestion noise */
|
||||
res = 2;
|
||||
write(sndcmd[1], &res, sizeof(res));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -529,7 +531,7 @@ static int oss_write(struct ast_channel *chan, struct ast_frame *f)
|
||||
return 0;
|
||||
/* Stop any currently playing sound */
|
||||
cursound = -1;
|
||||
if (!full_duplex && (strlen(digits) || needhangup || needanswer)) {
|
||||
if (!full_duplex) {
|
||||
/* If we're half duplex, we have to switch to read mode
|
||||
to honor immediate needs if necessary */
|
||||
res = soundcard_setinput(1);
|
||||
@@ -572,18 +574,11 @@ static struct ast_frame *oss_read(struct ast_channel *chan)
|
||||
static char buf[FRAME_SIZE * 2 + AST_FRIENDLY_OFFSET];
|
||||
static int readpos = 0;
|
||||
int res;
|
||||
int b;
|
||||
int nonull=0;
|
||||
|
||||
#if 0
|
||||
ast_log(LOG_DEBUG, "oss_read()\n");
|
||||
#endif
|
||||
|
||||
/* Acknowledge any pending cmd */
|
||||
res = read(cmd[0], &b, sizeof(b));
|
||||
if (res > 0)
|
||||
nonull = 1;
|
||||
|
||||
|
||||
f.frametype = AST_FRAME_NULL;
|
||||
f.subclass = 0;
|
||||
f.timelen = 0;
|
||||
@@ -593,44 +588,6 @@ static struct ast_frame *oss_read(struct ast_channel *chan)
|
||||
f.src = type;
|
||||
f.mallocd = 0;
|
||||
|
||||
if (needringing) {
|
||||
f.frametype = AST_FRAME_CONTROL;
|
||||
f.subclass = AST_CONTROL_RINGING;
|
||||
needringing = 0;
|
||||
return &f;
|
||||
}
|
||||
|
||||
if (needhangup) {
|
||||
needhangup = 0;
|
||||
return NULL;
|
||||
}
|
||||
if (strlen(text2send)) {
|
||||
f.frametype = AST_FRAME_TEXT;
|
||||
f.subclass = 0;
|
||||
f.data = text2send;
|
||||
f.datalen = strlen(text2send);
|
||||
strcpy(text2send,"");
|
||||
return &f;
|
||||
}
|
||||
if (strlen(digits)) {
|
||||
f.frametype = AST_FRAME_DTMF;
|
||||
f.subclass = digits[0];
|
||||
for (res=0;res<strlen(digits);res++)
|
||||
digits[res] = digits[res + 1];
|
||||
return &f;
|
||||
}
|
||||
|
||||
if (needanswer) {
|
||||
needanswer = 0;
|
||||
f.frametype = AST_FRAME_CONTROL;
|
||||
f.subclass = AST_CONTROL_ANSWER;
|
||||
chan->state = AST_STATE_UP;
|
||||
return &f;
|
||||
}
|
||||
|
||||
if (nonull)
|
||||
return &f;
|
||||
|
||||
res = soundcard_setinput(0);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to set input mode\n");
|
||||
@@ -709,12 +666,11 @@ static int oss_indicate(struct ast_channel *chan, int cond)
|
||||
static struct ast_channel *oss_new(struct chan_oss_pvt *p, int state)
|
||||
{
|
||||
struct ast_channel *tmp;
|
||||
tmp = ast_channel_alloc();
|
||||
tmp = ast_channel_alloc(1);
|
||||
if (tmp) {
|
||||
snprintf(tmp->name, sizeof(tmp->name), "OSS/%s", DEV_DSP + 5);
|
||||
tmp->type = type;
|
||||
tmp->fds[0] = sounddev;
|
||||
tmp->fds[1] = cmd[0];
|
||||
tmp->nativeformats = AST_FORMAT_SLINEAR;
|
||||
tmp->pvt->pvt = p;
|
||||
tmp->pvt->send_digit = oss_digit;
|
||||
@@ -727,11 +683,11 @@ static struct ast_channel *oss_new(struct chan_oss_pvt *p, int state)
|
||||
tmp->pvt->indicate = oss_indicate;
|
||||
tmp->pvt->fixup = oss_fixup;
|
||||
if (strlen(p->context))
|
||||
strncpy(tmp->context, p->context, sizeof(tmp->context));
|
||||
strncpy(tmp->context, p->context, sizeof(tmp->context)-1);
|
||||
if (strlen(p->exten))
|
||||
strncpy(tmp->exten, p->exten, sizeof(tmp->exten));
|
||||
strncpy(tmp->exten, p->exten, sizeof(tmp->exten)-1);
|
||||
if (strlen(language))
|
||||
strncpy(tmp->language, language, sizeof(tmp->language));
|
||||
strncpy(tmp->language, language, sizeof(tmp->language)-1);
|
||||
p->owner = tmp;
|
||||
tmp->state = state;
|
||||
ast_pthread_mutex_lock(&usecnt_lock);
|
||||
@@ -813,6 +769,7 @@ static char autoanswer_usage[] =
|
||||
|
||||
static int console_answer(int fd, int argc, char *argv[])
|
||||
{
|
||||
struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
|
||||
if (argc != 1)
|
||||
return RESULT_SHOWUSAGE;
|
||||
if (!oss.owner) {
|
||||
@@ -821,7 +778,7 @@ static int console_answer(int fd, int argc, char *argv[])
|
||||
}
|
||||
hookstate = 1;
|
||||
cursound = -1;
|
||||
needanswer++;
|
||||
ast_queue_frame(oss.owner, &f, 1);
|
||||
answer_sound();
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
@@ -833,6 +790,8 @@ static char sendtext_usage[] =
|
||||
static int console_sendtext(int fd, int argc, char *argv[])
|
||||
{
|
||||
int tmparg = 1;
|
||||
char text2send[256];
|
||||
struct ast_frame f = { 0, };
|
||||
if (argc < 1)
|
||||
return RESULT_SHOWUSAGE;
|
||||
if (!oss.owner) {
|
||||
@@ -846,7 +805,13 @@ static int console_sendtext(int fd, int argc, char *argv[])
|
||||
strncat(text2send, argv[tmparg++], sizeof(text2send) - strlen(text2send));
|
||||
strncat(text2send, " ", sizeof(text2send) - strlen(text2send));
|
||||
}
|
||||
needanswer++;
|
||||
if (strlen(text2send)) {
|
||||
f.frametype = AST_FRAME_TEXT;
|
||||
f.subclass = 0;
|
||||
f.data = text2send;
|
||||
f.datalen = strlen(text2send);
|
||||
ast_queue_frame(oss.owner, &f, 1);
|
||||
}
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -864,8 +829,9 @@ static int console_hangup(int fd, int argc, char *argv[])
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
hookstate = 0;
|
||||
if (oss.owner)
|
||||
needhangup++;
|
||||
if (oss.owner) {
|
||||
ast_queue_hangup(oss.owner, 1);
|
||||
}
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -878,14 +844,16 @@ static int console_dial(int fd, int argc, char *argv[])
|
||||
{
|
||||
char tmp[256], *tmp2;
|
||||
char *mye, *myc;
|
||||
int b = 0;
|
||||
int x;
|
||||
struct ast_frame f = { AST_FRAME_DTMF, 0 };
|
||||
if ((argc != 1) && (argc != 2))
|
||||
return RESULT_SHOWUSAGE;
|
||||
if (oss.owner) {
|
||||
if (argc == 2) {
|
||||
strncat(digits, argv[1], sizeof(digits) - strlen(digits));
|
||||
/* Wake up the polling thread */
|
||||
write(cmd[1], &b, sizeof(b));
|
||||
for (x=0;x<strlen(argv[1]);x++) {
|
||||
f.subclass = argv[1][x];
|
||||
ast_queue_frame(oss.owner, &f, 1);
|
||||
}
|
||||
} else {
|
||||
ast_cli(fd, "You're already in a call. You can use this only to dial digits until you hangup\n");
|
||||
return RESULT_FAILURE;
|
||||
@@ -895,7 +863,7 @@ static int console_dial(int fd, int argc, char *argv[])
|
||||
mye = exten;
|
||||
myc = context;
|
||||
if (argc == 2) {
|
||||
strncpy(tmp, argv[1], sizeof(tmp));
|
||||
strncpy(tmp, argv[1], sizeof(tmp)-1);
|
||||
strtok(tmp, "@");
|
||||
tmp2 = strtok(NULL, "@");
|
||||
if (strlen(tmp))
|
||||
@@ -904,8 +872,8 @@ static int console_dial(int fd, int argc, char *argv[])
|
||||
myc = tmp2;
|
||||
}
|
||||
if (ast_exists_extension(NULL, myc, mye, 1, NULL)) {
|
||||
strncpy(oss.exten, mye, sizeof(oss.exten));
|
||||
strncpy(oss.context, myc, sizeof(oss.context));
|
||||
strncpy(oss.exten, mye, sizeof(oss.exten)-1);
|
||||
strncpy(oss.context, myc, sizeof(oss.context)-1);
|
||||
hookstate = 1;
|
||||
oss_new(&oss, AST_STATE_UP);
|
||||
} else
|
||||
@@ -930,23 +898,15 @@ int load_module()
|
||||
{
|
||||
int res;
|
||||
int x;
|
||||
int flags;
|
||||
struct ast_config *cfg = ast_load(config);
|
||||
struct ast_variable *v;
|
||||
res = pipe(cmd);
|
||||
res = pipe(sndcmd);
|
||||
if (res) {
|
||||
ast_log(LOG_ERROR, "Unable to create pipe\n");
|
||||
return -1;
|
||||
}
|
||||
flags = fcntl(cmd[0], F_GETFL);
|
||||
fcntl(cmd[0], F_SETFL, flags | O_NONBLOCK);
|
||||
flags = fcntl(cmd[1], F_GETFL);
|
||||
fcntl(cmd[1], F_SETFL, flags | O_NONBLOCK);
|
||||
res = soundcard_init();
|
||||
if (res < 0) {
|
||||
close(cmd[1]);
|
||||
close(cmd[0]);
|
||||
if (option_verbose > 1) {
|
||||
ast_verbose(VERBOSE_PREFIX_2 "No sound card detected -- console channel will be unavailable\n");
|
||||
ast_verbose(VERBOSE_PREFIX_2 "Turn off OSS support by adding 'noload=chan_oss.so' in /etc/asterisk/modules.conf\n");
|
||||
@@ -972,11 +932,11 @@ int load_module()
|
||||
else if (!strcasecmp(v->name, "silencethreshold"))
|
||||
silencethreshold = atoi(v->value);
|
||||
else if (!strcasecmp(v->name, "context"))
|
||||
strncpy(context, v->value, sizeof(context));
|
||||
strncpy(context, v->value, sizeof(context)-1);
|
||||
else if (!strcasecmp(v->name, "language"))
|
||||
strncpy(language, v->value, sizeof(language));
|
||||
strncpy(language, v->value, sizeof(language)-1);
|
||||
else if (!strcasecmp(v->name, "extension"))
|
||||
strncpy(exten, v->value, sizeof(exten));
|
||||
strncpy(exten, v->value, sizeof(exten)-1);
|
||||
v=v->next;
|
||||
}
|
||||
ast_destroy(cfg);
|
||||
@@ -993,10 +953,6 @@ int unload_module()
|
||||
for (x=0;x<sizeof(myclis)/sizeof(struct ast_cli_entry); x++)
|
||||
ast_cli_unregister(myclis + x);
|
||||
close(sounddev);
|
||||
if (cmd[0] > 0) {
|
||||
close(cmd[0]);
|
||||
close(cmd[1]);
|
||||
}
|
||||
if (sndcmd[0] > 0) {
|
||||
close(sndcmd[0]);
|
||||
close(sndcmd[1]);
|
||||
|
||||
@@ -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,13 +611,15 @@ 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;
|
||||
tmp->fds[0] = i->fd;
|
||||
/* XXX Switching formats silently causes kernel panics XXX */
|
||||
tmp->nativeformats = prefformat;
|
||||
tmp->pvt->rawreadformat = prefformat;
|
||||
tmp->pvt->rawwriteformat = prefformat;
|
||||
tmp->state = state;
|
||||
if (state == AST_STATE_RING)
|
||||
tmp->rings = 1;
|
||||
@@ -599,11 +631,11 @@ static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *conte
|
||||
tmp->pvt->read = phone_read;
|
||||
tmp->pvt->write = phone_write;
|
||||
tmp->pvt->exception = phone_exception;
|
||||
strncpy(tmp->context, context, sizeof(tmp->context));
|
||||
strncpy(tmp->context, context, sizeof(tmp->context)-1);
|
||||
if (strlen(i->ext))
|
||||
strncpy(tmp->exten, i->ext, sizeof(tmp->exten));
|
||||
strncpy(tmp->exten, i->ext, sizeof(tmp->exten)-1);
|
||||
if (strlen(i->language))
|
||||
strncpy(tmp->language, i->language, sizeof(tmp->language));
|
||||
strncpy(tmp->language, i->language, sizeof(tmp->language)-1);
|
||||
if (strlen(i->callerid))
|
||||
tmp->callerid = strdup(i->callerid);
|
||||
i->owner = tmp;
|
||||
@@ -911,7 +943,7 @@ static struct phone_pvt *mkif(char *iface, int mode, int txgain, int rxgain)
|
||||
ast_log(LOG_DEBUG, "Unable to set port to PSTN\n");
|
||||
} else {
|
||||
if (ioctl(tmp->fd, IXJCTL_PORT, PORT_POTS))
|
||||
ast_log(LOG_DEBUG, "Unable to set port to PSTN\n");
|
||||
ast_log(LOG_DEBUG, "Unable to set port to POTS\n");
|
||||
}
|
||||
ioctl(tmp->fd, PHONE_PLAY_STOP);
|
||||
ioctl(tmp->fd, PHONE_REC_STOP);
|
||||
@@ -934,14 +966,14 @@ static struct phone_pvt *mkif(char *iface, int mode, int txgain, int rxgain)
|
||||
tmp->lastinput = -1;
|
||||
tmp->ministate = 0;
|
||||
memset(tmp->ext, 0, sizeof(tmp->ext));
|
||||
strncpy(tmp->language, language, sizeof(tmp->language));
|
||||
strncpy(tmp->dev, iface, sizeof(tmp->dev));
|
||||
strncpy(tmp->context, context, sizeof(tmp->context));
|
||||
strncpy(tmp->language, language, sizeof(tmp->language)-1);
|
||||
strncpy(tmp->dev, iface, sizeof(tmp->dev)-1);
|
||||
strncpy(tmp->context, context, sizeof(tmp->context)-1);
|
||||
tmp->next = NULL;
|
||||
tmp->obuflen = 0;
|
||||
tmp->dialtone = 0;
|
||||
tmp->cpt = 0;
|
||||
strncpy(tmp->callerid, callerid, sizeof(tmp->callerid));
|
||||
strncpy(tmp->callerid, callerid, sizeof(tmp->callerid)-1);
|
||||
tmp->txgain = txgain;
|
||||
ioctl(tmp->fd, PHONE_PLAY_VOLUME, tmp->txgain);
|
||||
tmp->rxgain = rxgain;
|
||||
@@ -1044,9 +1076,9 @@ int load_module()
|
||||
} else if (!strcasecmp(v->name, "silencesupression")) {
|
||||
silencesupression = ast_true(v->value);
|
||||
} else if (!strcasecmp(v->name, "language")) {
|
||||
strncpy(language, v->value, sizeof(language));
|
||||
strncpy(language, v->value, sizeof(language)-1);
|
||||
} else if (!strcasecmp(v->name, "callerid")) {
|
||||
strncpy(callerid, v->value, sizeof(callerid));
|
||||
strncpy(callerid, v->value, sizeof(callerid)-1);
|
||||
} else if (!strcasecmp(v->name, "mode")) {
|
||||
if (!strncasecmp(v->value, "di", 2))
|
||||
mode = MODE_DIALTONE;
|
||||
@@ -1057,7 +1089,7 @@ int load_module()
|
||||
else
|
||||
ast_log(LOG_WARNING, "Unknown mode: %s\n", v->value);
|
||||
} else if (!strcasecmp(v->name, "context")) {
|
||||
strncpy(context, v->value, sizeof(context));
|
||||
strncpy(context, v->value, sizeof(context)-1);
|
||||
} else if (!strcasecmp(v->name, "format")) {
|
||||
if (!strcasecmp(v->value, "g723.1")) {
|
||||
prefformat = AST_FORMAT_G723_1;
|
||||
@@ -1088,7 +1120,7 @@ int load_module()
|
||||
ast_pthread_mutex_unlock(&iflock);
|
||||
/* Make sure we can register our Adtranphone channel type */
|
||||
if (ast_channel_register(type, tdesc,
|
||||
AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW, phone_request)) {
|
||||
AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW, phone_request)) {
|
||||
ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
|
||||
ast_destroy(cfg);
|
||||
unload_module();
|
||||
|
||||
1951
channels/chan_sip.c
Normal file
1951
channels/chan_sip.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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>
|
||||
@@ -52,14 +53,14 @@ static char context[AST_MAX_EXTENSION] = "default";
|
||||
static char language[MAX_LANGUAGE] = "";
|
||||
|
||||
static int usecnt =0;
|
||||
static pthread_mutex_t usecnt_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t usecnt_lock = AST_MUTEX_INITIALIZER;
|
||||
|
||||
/* Protect the interface list (of vofr_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. */
|
||||
@@ -798,7 +799,7 @@ static int vofr_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
|
||||
static struct ast_channel *vofr_new(struct vofr_pvt *i, int state)
|
||||
{
|
||||
struct ast_channel *tmp;
|
||||
tmp = ast_channel_alloc();
|
||||
tmp = ast_channel_alloc(0);
|
||||
if (tmp) {
|
||||
#ifdef OLD_SANGOMA_API
|
||||
snprintf(tmp->name, sizeof(tmp->name), "AdtranVoFR/%s", i->sa.spkt_device);
|
||||
@@ -823,13 +824,13 @@ static struct ast_channel *vofr_new(struct vofr_pvt *i, int state)
|
||||
tmp->pvt->write = vofr_write;
|
||||
tmp->pvt->fixup = vofr_fixup;
|
||||
if (strlen(i->language))
|
||||
strncpy(tmp->language, i->language, sizeof(tmp->language));
|
||||
strncpy(tmp->language, i->language, sizeof(tmp->language)-1);
|
||||
i->owner = tmp;
|
||||
ast_pthread_mutex_lock(&usecnt_lock);
|
||||
usecnt++;
|
||||
ast_pthread_mutex_unlock(&usecnt_lock);
|
||||
ast_update_use_count();
|
||||
strncpy(tmp->context, i->context, sizeof(tmp->context));
|
||||
strncpy(tmp->context, i->context, sizeof(tmp->context)-1);
|
||||
if (state != AST_STATE_DOWN) {
|
||||
if (ast_pbx_start(tmp)) {
|
||||
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
|
||||
@@ -1050,7 +1051,7 @@ static struct vofr_pvt *mkif(char *type, char *iface)
|
||||
#ifdef OLD_SANGOMA_API
|
||||
/* Prepare sockaddr for binding */
|
||||
memset(&tmp->sa, 0, sizeof(tmp->sa));
|
||||
strncpy(tmp->sa.spkt_device, iface, sizeof(tmp->sa.spkt_device));
|
||||
strncpy(tmp->sa.spkt_device, iface, sizeof(tmp->sa.spkt_device)-1);
|
||||
tmp->sa.spkt_protocol = htons(0x16);
|
||||
tmp->sa.spkt_family = AF_PACKET;
|
||||
if (bind(tmp->s, (struct sockaddr *)&tmp->sa, sizeof(struct sockaddr))) {
|
||||
@@ -1059,8 +1060,8 @@ static struct vofr_pvt *mkif(char *type, char *iface)
|
||||
memset(&tmp->sa, 0, sizeof(tmp->sa));
|
||||
tmp->sa.sll_family = AF_WANPIPE;
|
||||
tmp->sa.sll_protocol = htons(ETH_P_IP);
|
||||
strncpy(tmp->sa.sll_device, iface, sizeof(tmp->sa.sll_device));
|
||||
strncpy(tmp->sa.sll_card, "wanpipe1", sizeof(tmp->sa.sll_card));
|
||||
strncpy(tmp->sa.sll_device, iface, sizeof(tmp->sa.sll_device)-1);
|
||||
strncpy(tmp->sa.sll_card, "wanpipe1", sizeof(tmp->sa.sll_card)-1);
|
||||
tmp->sa.sll_ifindex = 0;
|
||||
if (bind(tmp->s, (struct sockaddr *)&tmp->sa, sizeof(struct wan_sockaddr_ll))) {
|
||||
#endif
|
||||
@@ -1088,8 +1089,8 @@ static struct vofr_pvt *mkif(char *type, char *iface)
|
||||
tmp->dlcih = 0;
|
||||
tmp->cid = 1;
|
||||
tmp->ringgothangup = 0;
|
||||
strncpy(tmp->language, language, sizeof(tmp->language));
|
||||
strncpy(tmp->context, context, sizeof(tmp->context));
|
||||
strncpy(tmp->language, language, sizeof(tmp->language)-1);
|
||||
strncpy(tmp->context, context, sizeof(tmp->context)-1);
|
||||
/* User terminations are game for outgoing connections */
|
||||
if (!strcasecmp(type, "user"))
|
||||
tmp->outgoing = 1;
|
||||
@@ -1169,9 +1170,9 @@ int load_module()
|
||||
return -1;
|
||||
}
|
||||
} else if (!strcasecmp(v->name, "context")) {
|
||||
strncpy(context, v->value, sizeof(context));
|
||||
strncpy(context, v->value, sizeof(context)-1);
|
||||
} else if (!strcasecmp(v->name, "language")) {
|
||||
strncpy(language, v->value, sizeof(language));
|
||||
strncpy(language, v->value, sizeof(language)-1);
|
||||
}
|
||||
v = v->next;
|
||||
}
|
||||
|
||||
2081
channels/chan_zap.c
2081
channels/chan_zap.c
File diff suppressed because it is too large
Load Diff
157
channels/gentone-ulaw.c
Normal file
157
channels/gentone-ulaw.c
Normal file
@@ -0,0 +1,157 @@
|
||||
/* Generate a header file for a particular
|
||||
single or double frequency */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#define CLIP 32635
|
||||
#define BIAS 0x84
|
||||
static float loudness=16384.0;
|
||||
|
||||
static int calc_samples(int freq)
|
||||
{
|
||||
int x, samples;
|
||||
/* Calculate the number of samples at 8000hz sampling
|
||||
we need to have this wave form */
|
||||
samples = 8000;
|
||||
/* Take out common 2's up to six times */
|
||||
for (x=0;x<6;x++)
|
||||
if (!(freq % 2)) {
|
||||
freq /= 2;
|
||||
samples /= 2;
|
||||
}
|
||||
/* Take out common 5's (up to three times */
|
||||
for (x=0;x<3;x++)
|
||||
if (!(freq % 5)) {
|
||||
freq /= 5;
|
||||
samples /=5;
|
||||
}
|
||||
/* No more common factors. */
|
||||
return samples;
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine converts from linear to ulaw
|
||||
**
|
||||
** Craig Reese: IDA/Supercomputing Research Center
|
||||
** Joe Campbell: Department of Defense
|
||||
** 29 September 1989
|
||||
**
|
||||
** References:
|
||||
** 1) CCITT Recommendation G.711 (very difficult to follow)
|
||||
** 2) "A New Digital Technique for Implementation of Any
|
||||
** Continuous PCM Companding Law," Villeret, Michel,
|
||||
** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
|
||||
** 1973, pg. 11.12-11.17
|
||||
** 3) MIL-STD-188-113,"Interoperability and Performance Standards
|
||||
** for Analog-to_Digital Conversion Techniques,"
|
||||
** 17 February 1987
|
||||
**
|
||||
** Input: Signed 16 bit linear sample
|
||||
** Output: 8 bit ulaw sample
|
||||
*/
|
||||
|
||||
#define ZEROTRAP /* turn on the trap as per the MIL-STD */
|
||||
#define BIAS 0x84 /* define the add-in bias for 16 bit samples */
|
||||
#define CLIP 32635
|
||||
|
||||
static unsigned char linear2ulaw(short sample) {
|
||||
static int exp_lut[256] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
|
||||
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
|
||||
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
|
||||
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
|
||||
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
|
||||
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7};
|
||||
int sign, exponent, mantissa;
|
||||
unsigned char ulawbyte;
|
||||
|
||||
/* Get the sample into sign-magnitude. */
|
||||
sign = (sample >> 8) & 0x80; /* set aside the sign */
|
||||
if (sign != 0) sample = -sample; /* get magnitude */
|
||||
if (sample > CLIP) sample = CLIP; /* clip the magnitude */
|
||||
|
||||
/* Convert from 16 bit linear to ulaw. */
|
||||
sample = sample + BIAS;
|
||||
exponent = exp_lut[(sample >> 7) & 0xFF];
|
||||
mantissa = (sample >> (exponent + 3)) & 0x0F;
|
||||
ulawbyte = ~(sign | (exponent << 4) | mantissa);
|
||||
#ifdef ZEROTRAP
|
||||
if (ulawbyte == 0) ulawbyte = 0x02; /* optional CCITT trap */
|
||||
#endif
|
||||
|
||||
return(ulawbyte);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
FILE *f;
|
||||
int freq1, freq2;
|
||||
float wlen1, wlen2;
|
||||
float val;
|
||||
int x, samples1, samples2, samples=0;
|
||||
char fn[256];
|
||||
if (argc < 3) {
|
||||
fprintf(stderr, "Usage: gensound <name> <freq1> [freq2]\n");
|
||||
exit(1);
|
||||
}
|
||||
freq1 = atoi(argv[2]);
|
||||
if (argc > 3)
|
||||
freq2 = atoi(argv[3]);
|
||||
else
|
||||
freq2 = 0;
|
||||
wlen1 = 8000.0/(float)freq1;
|
||||
samples1 = calc_samples(freq1);
|
||||
printf("Wavelength 1 (in samples): %10.5f\n", wlen1);
|
||||
printf("Minimum samples (1): %d (%f.3 wavelengths)\n", samples1, samples1 / wlen1);
|
||||
if (freq2) {
|
||||
wlen2 = 8000.0/(float)freq2;
|
||||
samples2 = calc_samples(freq2);
|
||||
printf("Wavelength 1 (in samples): %10.5f\n", wlen2);
|
||||
printf("Minimum samples (1): %d (%f.3 wavelengths)\n", samples2, samples2 / wlen2);
|
||||
}
|
||||
samples = samples1;
|
||||
if (freq2) {
|
||||
while(samples % samples2)
|
||||
samples += samples1;
|
||||
}
|
||||
printf("Need %d samples\n", samples);
|
||||
snprintf(fn, sizeof(fn), "%s.h", argv[1]);
|
||||
if ((f = fopen(fn, "w"))) {
|
||||
if (freq2)
|
||||
fprintf(f, "/* %s: Generated from frequencies %d and %d \n"
|
||||
" by gentone. %d samples */\n", fn, freq1, freq2, samples);
|
||||
else
|
||||
fprintf(f, "/* %s: Generated from frequency %d\n"
|
||||
" by gentone. %d samples */\n", fn, freq1, samples);
|
||||
fprintf(f, "static unsigned char %s[%d] = {\n\t", argv[1], samples);
|
||||
for (x=0;x<samples;x++) {
|
||||
val = loudness * sin((freq1 * 2.0 * M_PI * x)/8000.0);
|
||||
if (freq2)
|
||||
val += loudness * sin((freq2 * 2.0 * M_PI * x)/8000.0);
|
||||
fprintf(f, "%3d, ", (int) linear2ulaw(val));
|
||||
if (!((x+1) % 8))
|
||||
fprintf(f, "\n\t");
|
||||
}
|
||||
if (x % 15)
|
||||
fprintf(f, "\n");
|
||||
fprintf(f, "};\n");
|
||||
fclose(f);
|
||||
printf("Wrote %s\n", fn);
|
||||
} else {
|
||||
fprintf(stderr, "Unable to open %s for writing\n", fn);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -69,10 +69,10 @@ int main(int argc, char *argv[])
|
||||
if ((f = fopen(fn, "w"))) {
|
||||
if (freq2)
|
||||
fprintf(f, "/* %s: Generated from frequencies %d and %d \n"
|
||||
" by gensound. %d samples */\n", fn, freq1, freq2, samples);
|
||||
" by gentone. %d samples */\n", fn, freq1, freq2, samples);
|
||||
else
|
||||
fprintf(f, "/* %s: Generated from frequency %d\n"
|
||||
" by gensound. %d samples */\n", fn, freq1, samples);
|
||||
" by gentone. %d samples */\n", fn, freq1, samples);
|
||||
fprintf(f, "static short %s[%d] = {\n\t", argv[1], samples);
|
||||
for (x=0;x<samples;x++) {
|
||||
val = loudness * sin((freq1 * 2.0 * M_PI * x)/8000.0);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/******************************************************************************
|
||||
$Id$
|
||||
$Log$
|
||||
Revision 1.10 1999/12/01 05:25:58 markster
|
||||
Version 0.1.9 from FTP
|
||||
Revision 1.13 1999/12/01 05:25:58 markster
|
||||
Version 0.1.12 from FTP
|
||||
|
||||
Revision 1.1 1999/12/01 05:25:58 markster
|
||||
Start on the Internet Phone Jack channel
|
||||
|
||||
33
cli.c
33
cli.c
@@ -43,7 +43,7 @@ void ast_cli(int fd, char *fmt, ...)
|
||||
write(fd, stuff, strlen(stuff));
|
||||
}
|
||||
|
||||
pthread_mutex_t clilock = PTHREAD_MUTEX_INITIALIZER;
|
||||
pthread_mutex_t clilock = AST_MUTEX_INITIALIZER;
|
||||
|
||||
|
||||
struct ast_cli_entry *helpers = NULL;
|
||||
@@ -154,7 +154,7 @@ static int handle_unload(int fd, int argc, char *argv[])
|
||||
#define MODLIST_FORMAT "%-20s %-40.40s %-10d\n"
|
||||
#define MODLIST_FORMAT2 "%-20s %-40.40s %-10s\n"
|
||||
|
||||
static pthread_mutex_t climodentrylock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t climodentrylock = AST_MUTEX_INITIALIZER;
|
||||
static int climodentryfd = -1;
|
||||
|
||||
static int modlist_modentry(char *module, char *description, int usecnt)
|
||||
@@ -325,7 +325,7 @@ static char *complete_fn(char *line, char *word, int pos, int state)
|
||||
if (pos != 1)
|
||||
return NULL;
|
||||
if (word[0] == '/')
|
||||
strncpy(filename, word, sizeof(filename));
|
||||
strncpy(filename, word, sizeof(filename)-1);
|
||||
else
|
||||
snprintf(filename, sizeof(filename), "%s/%s", AST_MODULE_DIR, word);
|
||||
c = (char*)filename_completion_function(filename, state);
|
||||
@@ -441,13 +441,17 @@ int ast_cli_unregister(struct ast_cli_entry *e)
|
||||
cur = helpers;
|
||||
while(cur) {
|
||||
if (e == cur) {
|
||||
/* Rewrite */
|
||||
if (l)
|
||||
l->next = e->next;
|
||||
else
|
||||
helpers = e->next;
|
||||
e->next = NULL;
|
||||
break;
|
||||
if (e->inuse) {
|
||||
ast_log(LOG_WARNING, "Can't remove command that is in use\n");
|
||||
} else {
|
||||
/* Rewrite */
|
||||
if (l)
|
||||
l->next = e->next;
|
||||
else
|
||||
helpers = e->next;
|
||||
e->next = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
l = cur;
|
||||
cur = cur->next;
|
||||
@@ -719,6 +723,9 @@ int ast_cli_command(int fd, char *s)
|
||||
if (x > 0) {
|
||||
ast_pthread_mutex_lock(&clilock);
|
||||
e = find_cli(argv, 0);
|
||||
if (e)
|
||||
e->inuse++;
|
||||
ast_pthread_mutex_unlock(&clilock);
|
||||
if (e) {
|
||||
switch(e->handler(fd, x, argv)) {
|
||||
case RESULT_SHOWUSAGE:
|
||||
@@ -728,7 +735,11 @@ int ast_cli_command(int fd, char *s)
|
||||
}
|
||||
} else
|
||||
ast_cli(fd, "No such command '%s' (type 'help' for help)\n", find_best(argv));
|
||||
ast_pthread_mutex_unlock(&clilock);
|
||||
if (e) {
|
||||
ast_pthread_mutex_lock(&clilock);
|
||||
e->inuse--;
|
||||
ast_pthread_mutex_unlock(&clilock);
|
||||
}
|
||||
}
|
||||
free(dup);
|
||||
} else {
|
||||
|
||||
@@ -25,10 +25,13 @@ 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
|
||||
|
||||
CODECS+=$(MODG723) codec_gsm.so codec_mp3_d.so codec_lpc10.so codec_adpcm.so codec_ulaw.so
|
||||
CODECS+=$(MODG723) codec_gsm.so codec_mp3_d.so codec_lpc10.so \
|
||||
codec_adpcm.so codec_ulaw.so codec_alaw.so codec_a_mu.so
|
||||
|
||||
all: $(CODECS)
|
||||
|
||||
@@ -43,7 +46,7 @@ clean:
|
||||
$(LIBG723):
|
||||
make -C g723.1 all
|
||||
|
||||
$(LIBGSM):
|
||||
gsm/lib/libgsm.a:
|
||||
make -C gsm lib/libgsm.a
|
||||
|
||||
$(LIBG723B):
|
||||
@@ -64,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)
|
||||
|
||||
326
codecs/codec_a_mu.c
Normal file
326
codecs/codec_a_mu.c
Normal file
@@ -0,0 +1,326 @@
|
||||
/* codec_a_mu.c - translate between alaw and ulaw directly
|
||||
*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Copyright (c) 2001 Linux Support Services, Inc. All rights reserved.
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/alaw.h>
|
||||
#include <asterisk/ulaw.h>
|
||||
#include <fcntl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define BUFFER_SIZE 8096 /* size for the translation buffers */
|
||||
|
||||
static pthread_mutex_t localuser_lock = AST_MUTEX_INITIALIZER;
|
||||
static int localusecnt = 0;
|
||||
|
||||
static char *tdesc = "A-law and Mulaw direct Coder/Decoder";
|
||||
|
||||
static unsigned char mu2a[256];
|
||||
static unsigned char a2mu[256];
|
||||
|
||||
/* Sample frame data (Mu data is okay) */
|
||||
|
||||
#include "ulaw_slin_ex.h"
|
||||
|
||||
/*
|
||||
* Private workspace for translating signed linear signals to alaw.
|
||||
*/
|
||||
|
||||
struct alaw_encoder_pvt
|
||||
{
|
||||
struct ast_frame f;
|
||||
char offset[AST_FRIENDLY_OFFSET]; /* Space to build offset */
|
||||
unsigned char outbuf[BUFFER_SIZE]; /* Encoded alaw, two nibbles to a word */
|
||||
int tail;
|
||||
};
|
||||
|
||||
/*
|
||||
* Private workspace for translating laws.
|
||||
*/
|
||||
|
||||
struct ulaw_encoder_pvt
|
||||
{
|
||||
struct ast_frame f;
|
||||
char offset[AST_FRIENDLY_OFFSET]; /* Space to build offset */
|
||||
unsigned char outbuf[BUFFER_SIZE]; /* Encoded ulaw values */
|
||||
int tail;
|
||||
};
|
||||
|
||||
static struct ast_translator_pvt *
|
||||
alawtoulaw_new ()
|
||||
{
|
||||
struct ulaw_encoder_pvt *tmp;
|
||||
tmp = malloc (sizeof (struct ulaw_encoder_pvt));
|
||||
if (tmp)
|
||||
{
|
||||
memset(tmp, 0, sizeof(*tmp));
|
||||
tmp->tail = 0;
|
||||
localusecnt++;
|
||||
ast_update_use_count ();
|
||||
}
|
||||
return (struct ast_translator_pvt *) tmp;
|
||||
}
|
||||
|
||||
static struct ast_translator_pvt *
|
||||
ulawtoalaw_new ()
|
||||
{
|
||||
struct alaw_encoder_pvt *tmp;
|
||||
tmp = malloc (sizeof (struct alaw_encoder_pvt));
|
||||
if (tmp)
|
||||
{
|
||||
memset(tmp, 0, sizeof(*tmp));
|
||||
localusecnt++;
|
||||
ast_update_use_count ();
|
||||
tmp->tail = 0;
|
||||
}
|
||||
return (struct ast_translator_pvt *) tmp;
|
||||
}
|
||||
|
||||
static int
|
||||
alawtoulaw_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
|
||||
{
|
||||
struct ulaw_encoder_pvt *tmp = (struct ulaw_encoder_pvt *) pvt;
|
||||
int x;
|
||||
unsigned char *b;
|
||||
|
||||
if ((tmp->tail + f->datalen)> sizeof(tmp->outbuf)) {
|
||||
ast_log(LOG_WARNING, "Out of buffer space\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Reset ssindex and signal to frame's specified values */
|
||||
b = f->data;
|
||||
for (x=0;x<f->datalen;x++)
|
||||
tmp->outbuf[tmp->tail + x] = a2mu[b[x]];
|
||||
|
||||
tmp->tail += f->datalen;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ast_frame *
|
||||
alawtoulaw_frameout (struct ast_translator_pvt *pvt)
|
||||
{
|
||||
struct ulaw_encoder_pvt *tmp = (struct ulaw_encoder_pvt *) pvt;
|
||||
|
||||
if (!tmp->tail)
|
||||
return NULL;
|
||||
|
||||
tmp->f.frametype = AST_FRAME_VOICE;
|
||||
tmp->f.subclass = AST_FORMAT_ULAW;
|
||||
tmp->f.datalen = tmp->tail;
|
||||
tmp->f.timelen = tmp->tail / 8;
|
||||
tmp->f.mallocd = 0;
|
||||
tmp->f.offset = AST_FRIENDLY_OFFSET;
|
||||
tmp->f.src = __PRETTY_FUNCTION__;
|
||||
tmp->f.data = tmp->outbuf;
|
||||
tmp->tail = 0;
|
||||
return &tmp->f;
|
||||
}
|
||||
|
||||
static int
|
||||
ulawtoalaw_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
|
||||
{
|
||||
struct alaw_encoder_pvt *tmp = (struct alaw_encoder_pvt *) pvt;
|
||||
int x;
|
||||
unsigned char *s;
|
||||
if (tmp->tail + f->datalen >= sizeof(tmp->outbuf))
|
||||
{
|
||||
ast_log (LOG_WARNING, "Out of buffer space\n");
|
||||
return -1;
|
||||
}
|
||||
s = f->data;
|
||||
for (x=0;x<f->datalen;x++)
|
||||
tmp->outbuf[x+tmp->tail] = mu2a[s[x]];
|
||||
tmp->tail += f->datalen;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* LinToalaw_FrameOut
|
||||
* Convert a buffer of raw 16-bit signed linear PCM to a buffer
|
||||
* of 4-bit alaw packed two to a byte (Big Endian).
|
||||
*
|
||||
* Results:
|
||||
* Foo
|
||||
*
|
||||
* Side effects:
|
||||
* Leftover inbuf data gets packed, tail gets updated.
|
||||
*/
|
||||
|
||||
static struct ast_frame *
|
||||
ulawtoalaw_frameout (struct ast_translator_pvt *pvt)
|
||||
{
|
||||
struct alaw_encoder_pvt *tmp = (struct alaw_encoder_pvt *) pvt;
|
||||
|
||||
if (tmp->tail) {
|
||||
tmp->f.frametype = AST_FRAME_VOICE;
|
||||
tmp->f.subclass = AST_FORMAT_ALAW;
|
||||
tmp->f.timelen = tmp->tail / 8;
|
||||
tmp->f.mallocd = 0;
|
||||
tmp->f.offset = AST_FRIENDLY_OFFSET;
|
||||
tmp->f.src = __PRETTY_FUNCTION__;
|
||||
tmp->f.data = tmp->outbuf;
|
||||
tmp->f.datalen = tmp->tail;
|
||||
tmp->tail = 0;
|
||||
return &tmp->f;
|
||||
} else return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* alawToLin_Sample
|
||||
*/
|
||||
|
||||
static struct ast_frame *
|
||||
alawtoulaw_sample ()
|
||||
{
|
||||
static struct ast_frame f;
|
||||
f.frametype = AST_FRAME_VOICE;
|
||||
f.subclass = AST_FORMAT_ALAW;
|
||||
f.datalen = sizeof (ulaw_slin_ex);
|
||||
f.timelen = sizeof(ulaw_slin_ex) / 8;
|
||||
f.mallocd = 0;
|
||||
f.offset = 0;
|
||||
f.src = __PRETTY_FUNCTION__;
|
||||
f.data = ulaw_slin_ex;
|
||||
return &f;
|
||||
}
|
||||
|
||||
static struct ast_frame *
|
||||
ulawtoalaw_sample ()
|
||||
{
|
||||
static struct ast_frame f;
|
||||
f.frametype = AST_FRAME_VOICE;
|
||||
f.subclass = AST_FORMAT_ULAW;
|
||||
f.datalen = sizeof (ulaw_slin_ex);
|
||||
f.timelen = sizeof(ulaw_slin_ex) / 8;
|
||||
f.mallocd = 0;
|
||||
f.offset = 0;
|
||||
f.src = __PRETTY_FUNCTION__;
|
||||
f.data = ulaw_slin_ex;
|
||||
return &f;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* alaw_Destroy
|
||||
* Destroys a private workspace.
|
||||
*
|
||||
* Results:
|
||||
* It's gone!
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*/
|
||||
|
||||
static void
|
||||
alaw_destroy (struct ast_translator_pvt *pvt)
|
||||
{
|
||||
free (pvt);
|
||||
localusecnt--;
|
||||
ast_update_use_count ();
|
||||
}
|
||||
|
||||
/*
|
||||
* The complete translator for alawToLin.
|
||||
*/
|
||||
|
||||
static struct ast_translator alawtoulaw = {
|
||||
"alawtoulaw",
|
||||
AST_FORMAT_ALAW,
|
||||
AST_FORMAT_ULAW,
|
||||
alawtoulaw_new,
|
||||
alawtoulaw_framein,
|
||||
alawtoulaw_frameout,
|
||||
alaw_destroy,
|
||||
/* NULL */
|
||||
alawtoulaw_sample
|
||||
};
|
||||
|
||||
/*
|
||||
* The complete translator for LinToalaw.
|
||||
*/
|
||||
|
||||
static struct ast_translator ulawtoalaw = {
|
||||
"ulawtoalaw",
|
||||
AST_FORMAT_ULAW,
|
||||
AST_FORMAT_ALAW,
|
||||
ulawtoalaw_new,
|
||||
ulawtoalaw_framein,
|
||||
ulawtoalaw_frameout,
|
||||
alaw_destroy,
|
||||
/* NULL */
|
||||
ulawtoalaw_sample
|
||||
};
|
||||
|
||||
int
|
||||
unload_module (void)
|
||||
{
|
||||
int res;
|
||||
ast_pthread_mutex_lock (&localuser_lock);
|
||||
res = ast_unregister_translator (&ulawtoalaw);
|
||||
if (!res)
|
||||
res = ast_unregister_translator (&alawtoulaw);
|
||||
if (localusecnt)
|
||||
res = -1;
|
||||
ast_pthread_mutex_unlock (&localuser_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
load_module (void)
|
||||
{
|
||||
int res;
|
||||
int x;
|
||||
for (x=0;x<256;x++) {
|
||||
mu2a[x] = AST_LIN2A(AST_MULAW(x));
|
||||
a2mu[x] = AST_LIN2MU(AST_ALAW(x));
|
||||
}
|
||||
res = ast_register_translator (&alawtoulaw);
|
||||
if (!res)
|
||||
res = ast_register_translator (&ulawtoalaw);
|
||||
else
|
||||
ast_unregister_translator (&alawtoulaw);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a description of this module.
|
||||
*/
|
||||
|
||||
char *
|
||||
description (void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int
|
||||
usecount (void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT (res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *
|
||||
key ()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
@@ -13,6 +13,7 @@
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
@@ -27,7 +28,7 @@
|
||||
|
||||
#define BUFFER_SIZE 8096 /* size for the translation buffers */
|
||||
|
||||
static pthread_mutex_t localuser_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t localuser_lock = AST_MUTEX_INITIALIZER;
|
||||
static int localusecnt = 0;
|
||||
|
||||
static char *tdesc = "Adaptive Differential PCM Coder/Decoder";
|
||||
|
||||
379
codecs/codec_alaw.c
Normal file
379
codecs/codec_alaw.c
Normal file
@@ -0,0 +1,379 @@
|
||||
/* codec_alaw.c - translate between signed linear and alaw
|
||||
*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Copyright (c) 2001 Linux Support Services, Inc. All rights reserved.
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/alaw.h>
|
||||
#include <fcntl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define BUFFER_SIZE 8096 /* size for the translation buffers */
|
||||
|
||||
static pthread_mutex_t localuser_lock = AST_MUTEX_INITIALIZER;
|
||||
static int localusecnt = 0;
|
||||
|
||||
static char *tdesc = "A-law Coder/Decoder";
|
||||
|
||||
/* Sample frame data (Mu data is okay) */
|
||||
|
||||
#include "slin_ulaw_ex.h"
|
||||
#include "ulaw_slin_ex.h"
|
||||
|
||||
/*
|
||||
* Private workspace for translating signed linear signals to alaw.
|
||||
*/
|
||||
|
||||
struct alaw_encoder_pvt
|
||||
{
|
||||
struct ast_frame f;
|
||||
char offset[AST_FRIENDLY_OFFSET]; /* Space to build offset */
|
||||
unsigned char outbuf[BUFFER_SIZE]; /* Encoded alaw, two nibbles to a word */
|
||||
int tail;
|
||||
};
|
||||
|
||||
/*
|
||||
* Private workspace for translating alaw signals to signed linear.
|
||||
*/
|
||||
|
||||
struct alaw_decoder_pvt
|
||||
{
|
||||
struct ast_frame f;
|
||||
char offset[AST_FRIENDLY_OFFSET]; /* Space to build offset */
|
||||
short outbuf[BUFFER_SIZE]; /* Decoded signed linear values */
|
||||
int tail;
|
||||
};
|
||||
|
||||
/*
|
||||
* alawToLin_New
|
||||
* Create a new instance of alaw_decoder_pvt.
|
||||
*
|
||||
* Results:
|
||||
* Returns a pointer to the new instance.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*/
|
||||
|
||||
static struct ast_translator_pvt *
|
||||
alawtolin_new ()
|
||||
{
|
||||
struct alaw_decoder_pvt *tmp;
|
||||
tmp = malloc (sizeof (struct alaw_decoder_pvt));
|
||||
if (tmp)
|
||||
{
|
||||
memset(tmp, 0, sizeof(*tmp));
|
||||
tmp->tail = 0;
|
||||
localusecnt++;
|
||||
ast_update_use_count ();
|
||||
}
|
||||
return (struct ast_translator_pvt *) tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* LinToalaw_New
|
||||
* Create a new instance of alaw_encoder_pvt.
|
||||
*
|
||||
* Results:
|
||||
* Returns a pointer to the new instance.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*/
|
||||
|
||||
static struct ast_translator_pvt *
|
||||
lintoalaw_new ()
|
||||
{
|
||||
struct alaw_encoder_pvt *tmp;
|
||||
tmp = malloc (sizeof (struct alaw_encoder_pvt));
|
||||
if (tmp)
|
||||
{
|
||||
memset(tmp, 0, sizeof(*tmp));
|
||||
localusecnt++;
|
||||
ast_update_use_count ();
|
||||
tmp->tail = 0;
|
||||
}
|
||||
return (struct ast_translator_pvt *) tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* alawToLin_FrameIn
|
||||
* Fill an input buffer with packed 4-bit alaw values if there is room
|
||||
* left.
|
||||
*
|
||||
* Results:
|
||||
* Foo
|
||||
*
|
||||
* Side effects:
|
||||
* tmp->tail is the number of packed values in the buffer.
|
||||
*/
|
||||
|
||||
static int
|
||||
alawtolin_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
|
||||
{
|
||||
struct alaw_decoder_pvt *tmp = (struct alaw_decoder_pvt *) pvt;
|
||||
int x;
|
||||
unsigned char *b;
|
||||
|
||||
if ((tmp->tail + f->datalen) * 2 > sizeof(tmp->outbuf)) {
|
||||
ast_log(LOG_WARNING, "Out of buffer space\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Reset ssindex and signal to frame's specified values */
|
||||
b = f->data;
|
||||
for (x=0;x<f->datalen;x++)
|
||||
tmp->outbuf[tmp->tail + x] = AST_ALAW(b[x]);
|
||||
|
||||
tmp->tail += f->datalen;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* alawToLin_FrameOut
|
||||
* Convert 4-bit alaw encoded signals to 16-bit signed linear.
|
||||
*
|
||||
* Results:
|
||||
* Converted signals are placed in tmp->f.data, tmp->f.datalen
|
||||
* and tmp->f.timelen are calculated.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*/
|
||||
|
||||
static struct ast_frame *
|
||||
alawtolin_frameout (struct ast_translator_pvt *pvt)
|
||||
{
|
||||
struct alaw_decoder_pvt *tmp = (struct alaw_decoder_pvt *) pvt;
|
||||
|
||||
if (!tmp->tail)
|
||||
return NULL;
|
||||
|
||||
tmp->f.frametype = AST_FRAME_VOICE;
|
||||
tmp->f.subclass = AST_FORMAT_SLINEAR;
|
||||
tmp->f.datalen = tmp->tail *2;
|
||||
tmp->f.timelen = tmp->tail / 8;
|
||||
tmp->f.mallocd = 0;
|
||||
tmp->f.offset = AST_FRIENDLY_OFFSET;
|
||||
tmp->f.src = __PRETTY_FUNCTION__;
|
||||
tmp->f.data = tmp->outbuf;
|
||||
tmp->tail = 0;
|
||||
return &tmp->f;
|
||||
}
|
||||
|
||||
/*
|
||||
* LinToalaw_FrameIn
|
||||
* Fill an input buffer with 16-bit signed linear PCM values.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* tmp->tail is number of signal values in the input buffer.
|
||||
*/
|
||||
|
||||
static int
|
||||
lintoalaw_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
|
||||
{
|
||||
struct alaw_encoder_pvt *tmp = (struct alaw_encoder_pvt *) pvt;
|
||||
int x;
|
||||
short *s;
|
||||
if (tmp->tail + f->datalen/2 >= sizeof(tmp->outbuf))
|
||||
{
|
||||
ast_log (LOG_WARNING, "Out of buffer space\n");
|
||||
return -1;
|
||||
}
|
||||
s = f->data;
|
||||
for (x=0;x<f->datalen/2;x++)
|
||||
tmp->outbuf[x+tmp->tail] = AST_LIN2A(s[x]);
|
||||
tmp->tail += f->datalen/2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* LinToalaw_FrameOut
|
||||
* Convert a buffer of raw 16-bit signed linear PCM to a buffer
|
||||
* of 4-bit alaw packed two to a byte (Big Endian).
|
||||
*
|
||||
* Results:
|
||||
* Foo
|
||||
*
|
||||
* Side effects:
|
||||
* Leftover inbuf data gets packed, tail gets updated.
|
||||
*/
|
||||
|
||||
static struct ast_frame *
|
||||
lintoalaw_frameout (struct ast_translator_pvt *pvt)
|
||||
{
|
||||
struct alaw_encoder_pvt *tmp = (struct alaw_encoder_pvt *) pvt;
|
||||
|
||||
if (tmp->tail) {
|
||||
tmp->f.frametype = AST_FRAME_VOICE;
|
||||
tmp->f.subclass = AST_FORMAT_ALAW;
|
||||
tmp->f.timelen = tmp->tail / 8;
|
||||
tmp->f.mallocd = 0;
|
||||
tmp->f.offset = AST_FRIENDLY_OFFSET;
|
||||
tmp->f.src = __PRETTY_FUNCTION__;
|
||||
tmp->f.data = tmp->outbuf;
|
||||
tmp->f.datalen = tmp->tail;
|
||||
tmp->tail = 0;
|
||||
return &tmp->f;
|
||||
} else return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* alawToLin_Sample
|
||||
*/
|
||||
|
||||
static struct ast_frame *
|
||||
alawtolin_sample ()
|
||||
{
|
||||
static struct ast_frame f;
|
||||
f.frametype = AST_FRAME_VOICE;
|
||||
f.subclass = AST_FORMAT_ALAW;
|
||||
f.datalen = sizeof (ulaw_slin_ex);
|
||||
f.timelen = sizeof(ulaw_slin_ex) / 8;
|
||||
f.mallocd = 0;
|
||||
f.offset = 0;
|
||||
f.src = __PRETTY_FUNCTION__;
|
||||
f.data = ulaw_slin_ex;
|
||||
return &f;
|
||||
}
|
||||
|
||||
/*
|
||||
* LinToalaw_Sample
|
||||
*/
|
||||
|
||||
static struct ast_frame *
|
||||
lintoalaw_sample ()
|
||||
{
|
||||
static struct ast_frame f;
|
||||
f.frametype = AST_FRAME_VOICE;
|
||||
f.subclass = AST_FORMAT_SLINEAR;
|
||||
f.datalen = sizeof (slin_ulaw_ex);
|
||||
/* Assume 8000 Hz */
|
||||
f.timelen = sizeof (slin_ulaw_ex) / 16;
|
||||
f.mallocd = 0;
|
||||
f.offset = 0;
|
||||
f.src = __PRETTY_FUNCTION__;
|
||||
f.data = slin_ulaw_ex;
|
||||
return &f;
|
||||
}
|
||||
|
||||
/*
|
||||
* alaw_Destroy
|
||||
* Destroys a private workspace.
|
||||
*
|
||||
* Results:
|
||||
* It's gone!
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*/
|
||||
|
||||
static void
|
||||
alaw_destroy (struct ast_translator_pvt *pvt)
|
||||
{
|
||||
free (pvt);
|
||||
localusecnt--;
|
||||
ast_update_use_count ();
|
||||
}
|
||||
|
||||
/*
|
||||
* The complete translator for alawToLin.
|
||||
*/
|
||||
|
||||
static struct ast_translator alawtolin = {
|
||||
"alawtolin",
|
||||
AST_FORMAT_ALAW,
|
||||
AST_FORMAT_SLINEAR,
|
||||
alawtolin_new,
|
||||
alawtolin_framein,
|
||||
alawtolin_frameout,
|
||||
alaw_destroy,
|
||||
/* NULL */
|
||||
alawtolin_sample
|
||||
};
|
||||
|
||||
/*
|
||||
* The complete translator for LinToalaw.
|
||||
*/
|
||||
|
||||
static struct ast_translator lintoalaw = {
|
||||
"lintoalaw",
|
||||
AST_FORMAT_SLINEAR,
|
||||
AST_FORMAT_ALAW,
|
||||
lintoalaw_new,
|
||||
lintoalaw_framein,
|
||||
lintoalaw_frameout,
|
||||
alaw_destroy,
|
||||
/* NULL */
|
||||
lintoalaw_sample
|
||||
};
|
||||
|
||||
int
|
||||
unload_module (void)
|
||||
{
|
||||
int res;
|
||||
ast_pthread_mutex_lock (&localuser_lock);
|
||||
res = ast_unregister_translator (&lintoalaw);
|
||||
if (!res)
|
||||
res = ast_unregister_translator (&alawtolin);
|
||||
if (localusecnt)
|
||||
res = -1;
|
||||
ast_pthread_mutex_unlock (&localuser_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
load_module (void)
|
||||
{
|
||||
int res;
|
||||
res = ast_register_translator (&alawtolin);
|
||||
if (!res)
|
||||
res = ast_register_translator (&lintoalaw);
|
||||
else
|
||||
ast_unregister_translator (&alawtolin);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a description of this module.
|
||||
*/
|
||||
|
||||
char *
|
||||
description (void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int
|
||||
usecount (void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT (res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *
|
||||
key ()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
@@ -54,7 +54,7 @@
|
||||
#include "slin_g723_ex.h"
|
||||
#include "g723_slin_ex.h"
|
||||
|
||||
static pthread_mutex_t localuser_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t localuser_lock = AST_MUTEX_INITIALIZER;
|
||||
static int localusecnt=0;
|
||||
|
||||
#ifdef ANNEX_B
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#define TYPE_LOW 0x1
|
||||
#define TYPE_MASK 0x3
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/logger.h>
|
||||
@@ -37,7 +38,7 @@
|
||||
#include "slin_gsm_ex.h"
|
||||
#include "gsm_slin_ex.h"
|
||||
|
||||
static pthread_mutex_t localuser_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t localuser_lock = AST_MUTEX_INITIALIZER;
|
||||
static int localusecnt=0;
|
||||
|
||||
static char *tdesc = "GSM/PCM16 (signed linear) Codec Translator";
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/logger.h>
|
||||
@@ -42,7 +43,7 @@
|
||||
|
||||
#define LPC10_BYTES_IN_COMPRESSED_FRAME (LPC10_BITS_IN_COMPRESSED_FRAME + 7)/8
|
||||
|
||||
static pthread_mutex_t localuser_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t localuser_lock = AST_MUTEX_INITIALIZER;
|
||||
static int localusecnt=0;
|
||||
|
||||
static char *tdesc = "LPC10 2.4kbps (signed linear) Voice Coder";
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/logger.h>
|
||||
@@ -40,7 +41,7 @@
|
||||
#define MAX_FRAME_SIZE 1441
|
||||
#define MAX_OUTPUT_LEN 2304
|
||||
|
||||
static pthread_mutex_t localuser_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t localuser_lock = AST_MUTEX_INITIALIZER;
|
||||
static int localusecnt=0;
|
||||
|
||||
static char *tdesc = "MP3/PCM16 (signed linear) Translator (Decoder only)";
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
@@ -25,7 +26,7 @@
|
||||
|
||||
#define BUFFER_SIZE 8096 /* size for the translation buffers */
|
||||
|
||||
static pthread_mutex_t localuser_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t localuser_lock = AST_MUTEX_INITIALIZER;
|
||||
static int localusecnt = 0;
|
||||
|
||||
static char *tdesc = "Mu-law Coder/Decoder";
|
||||
@@ -138,7 +139,7 @@ ulawtolin_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
|
||||
/* Reset ssindex and signal to frame's specified values */
|
||||
b = f->data;
|
||||
for (x=0;x<f->datalen;x++)
|
||||
tmp->outbuf[tmp->tail + x] = ast_mulaw[b[x]];
|
||||
tmp->outbuf[tmp->tail + x] = AST_MULAW(b[x]);
|
||||
|
||||
tmp->tail += f->datalen;
|
||||
return 0;
|
||||
@@ -200,7 +201,7 @@ lintoulaw_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
|
||||
}
|
||||
s = f->data;
|
||||
for (x=0;x<f->datalen/2;x++)
|
||||
tmp->outbuf[x+tmp->tail] = ast_lin2mu[s[x]+32768];
|
||||
tmp->outbuf[x+tmp->tail] = AST_LIN2MU(s[x]);
|
||||
tmp->tail += f->datalen/2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
|
||||
$Log$
|
||||
Revision 1.8 2000/01/05 08:20:39 markster
|
||||
Version 0.1.9 from FTP
|
||||
Revision 1.11 2000/01/05 08:20:39 markster
|
||||
Version 0.1.12 from FTP
|
||||
|
||||
Revision 1.2 2000/01/05 08:20:39 markster
|
||||
Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -79,8 +79,8 @@ static integer c__1 = 1;
|
||||
/* ANALYS Version 55 */
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -246,8 +246,8 @@ static integer c__1 = 1;
|
||||
real phi[100] /* was [10][10] */, psi[10];
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -277,8 +277,8 @@ static integer c__1 = 1;
|
||||
/* Frame size, Prediction order, Pitch period */
|
||||
/* Arguments to ANALYS */
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
|
||||
$Log$
|
||||
Revision 1.8 2000/01/05 08:20:39 markster
|
||||
Version 0.1.9 from FTP
|
||||
Revision 1.11 2000/01/05 08:20:39 markster
|
||||
Version 0.1.12 from FTP
|
||||
|
||||
Revision 1.2 2000/01/05 08:20:39 markster
|
||||
Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -48,8 +48,8 @@ extern struct {
|
||||
/* BSYNZ Version 54 */
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -144,8 +144,8 @@ extern struct {
|
||||
real lpi0, hpi0;
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -175,8 +175,8 @@ extern struct {
|
||||
/* Frame size, Prediction order, Pitch period */
|
||||
/* Arguments */
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
|
||||
$Log$
|
||||
Revision 1.8 2000/01/05 08:20:39 markster
|
||||
Version 0.1.9 from FTP
|
||||
Revision 1.11 2000/01/05 08:20:39 markster
|
||||
Version 0.1.12 from FTP
|
||||
|
||||
Revision 1.2 2000/01/05 08:20:39 markster
|
||||
Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -35,8 +35,8 @@ extern int chanrd_(integer *order, integer *ipitv, integer *irms, integer *irc,
|
||||
/* CHANL Version 49 */
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
|
||||
$Log$
|
||||
Revision 1.8 2000/01/05 08:20:39 markster
|
||||
Version 0.1.9 from FTP
|
||||
Revision 1.11 2000/01/05 08:20:39 markster
|
||||
Version 0.1.12 from FTP
|
||||
|
||||
Revision 1.2 2000/01/05 08:20:39 markster
|
||||
Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -29,8 +29,8 @@ extern int dcbias_(integer *len, real *speech, real *sigout);
|
||||
/* DCBIAS Version 50 */
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
|
||||
$Log$
|
||||
Revision 1.8 2000/01/05 08:20:39 markster
|
||||
Version 0.1.9 from FTP
|
||||
Revision 1.11 2000/01/05 08:20:39 markster
|
||||
Version 0.1.12 from FTP
|
||||
|
||||
Revision 1.2 2000/01/05 08:20:39 markster
|
||||
Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -53,8 +53,8 @@ static integer c__2 = 2;
|
||||
/* DECODE Version 54 */
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -188,8 +188,8 @@ static integer c__2 = 2;
|
||||
integer ishift, errcnt, lsb;
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -219,8 +219,8 @@ static integer c__2 = 2;
|
||||
/* Frame size, Prediction order, Pitch period */
|
||||
/* Arguments */
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
|
||||
$Log$
|
||||
Revision 1.8 2000/01/05 08:20:39 markster
|
||||
Version 0.1.9 from FTP
|
||||
Revision 1.11 2000/01/05 08:20:39 markster
|
||||
Version 0.1.12 from FTP
|
||||
|
||||
Revision 1.2 2000/01/05 08:20:39 markster
|
||||
Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -37,8 +37,8 @@ extern int deemp_(real *x, integer *n, struct lpc10_decoder_state *st);
|
||||
/* DEEMP Version 48 */
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
|
||||
$Log$
|
||||
Revision 1.8 2000/01/05 08:20:39 markster
|
||||
Version 0.1.9 from FTP
|
||||
Revision 1.11 2000/01/05 08:20:39 markster
|
||||
Version 0.1.12 from FTP
|
||||
|
||||
Revision 1.2 2000/01/05 08:20:39 markster
|
||||
Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -29,8 +29,8 @@ extern int difmag_(real *speech, integer *lpita, integer *tau, integer *ltau, in
|
||||
/* DIFMAG Version 49 */
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
|
||||
$Log$
|
||||
Revision 1.8 2000/01/05 08:20:39 markster
|
||||
Version 0.1.9 from FTP
|
||||
Revision 1.11 2000/01/05 08:20:39 markster
|
||||
Version 0.1.12 from FTP
|
||||
|
||||
Revision 1.2 2000/01/05 08:20:39 markster
|
||||
Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -47,8 +47,8 @@ extern struct {
|
||||
/* DYPTRK Version 52 */
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -136,8 +136,8 @@ extern struct {
|
||||
|
||||
/* Arguments */
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
|
||||
$Log$
|
||||
Revision 1.8 2000/01/05 08:20:39 markster
|
||||
Version 0.1.9 from FTP
|
||||
Revision 1.11 2000/01/05 08:20:39 markster
|
||||
Version 0.1.12 from FTP
|
||||
|
||||
Revision 1.2 2000/01/05 08:20:39 markster
|
||||
Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -43,8 +43,8 @@ static integer c__2 = 2;
|
||||
/* ENCODE Version 54 */
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -128,8 +128,8 @@ static integer c__2 = 2;
|
||||
integer idel, nbit, i__, j, i2, i3, mrk;
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -151,8 +151,8 @@ static integer c__2 = 2;
|
||||
/* Frame size, Prediction order, Pitch period */
|
||||
/* Arguments */
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
|
||||
$Log$
|
||||
Revision 1.8 2000/01/05 08:20:39 markster
|
||||
Version 0.1.9 from FTP
|
||||
Revision 1.11 2000/01/05 08:20:39 markster
|
||||
Version 0.1.12 from FTP
|
||||
|
||||
Revision 1.2 2000/01/05 08:20:39 markster
|
||||
Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -29,8 +29,8 @@ extern int energy_(integer *len, real *speech, real *rms);
|
||||
/* ENERGY Version 50 */
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
|
||||
$Log$
|
||||
Revision 1.8 2000/01/05 08:20:39 markster
|
||||
Version 0.1.9 from FTP
|
||||
Revision 1.11 2000/01/05 08:20:39 markster
|
||||
Version 0.1.12 from FTP
|
||||
|
||||
Revision 1.2 2000/01/05 08:20:39 markster
|
||||
Some OSS fixes and a few lpc changes to make it actually work
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
|
||||
$Log$
|
||||
Revision 1.8 2000/01/05 08:20:39 markster
|
||||
Version 0.1.9 from FTP
|
||||
Revision 1.11 2000/01/05 08:20:39 markster
|
||||
Version 0.1.12 from FTP
|
||||
|
||||
Revision 1.2 2000/01/05 08:20:39 markster
|
||||
Some OSS fixes and a few lpc changes to make it actually work
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
|
||||
$Log$
|
||||
Revision 1.8 2000/01/05 08:20:39 markster
|
||||
Version 0.1.9 from FTP
|
||||
Revision 1.11 2000/01/05 08:20:39 markster
|
||||
Version 0.1.12 from FTP
|
||||
|
||||
Revision 1.2 2000/01/05 08:20:39 markster
|
||||
Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -29,8 +29,8 @@ extern int ham84_(integer *input, integer *output, integer *errcnt);
|
||||
/* HAM84 Version 45G */
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
|
||||
$Log$
|
||||
Revision 1.8 2000/01/05 08:20:39 markster
|
||||
Version 0.1.9 from FTP
|
||||
Revision 1.11 2000/01/05 08:20:39 markster
|
||||
Version 0.1.12 from FTP
|
||||
|
||||
Revision 1.2 2000/01/05 08:20:39 markster
|
||||
Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -39,8 +39,8 @@ extern int inithp100_(void);
|
||||
/* HP100 Version 55 */
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
|
||||
$Log$
|
||||
Revision 1.8 2000/01/05 08:20:39 markster
|
||||
Version 0.1.9 from FTP
|
||||
Revision 1.11 2000/01/05 08:20:39 markster
|
||||
Version 0.1.12 from FTP
|
||||
|
||||
Revision 1.2 2000/01/05 08:20:39 markster
|
||||
Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -29,8 +29,8 @@ extern int invert_(integer *order, real *phi, real *psi, real *rc);
|
||||
/* INVERT Version 45G */
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -91,8 +91,8 @@ extern int invert_(integer *order, real *phi, real *psi, real *rc);
|
||||
|
||||
/* Arguments */
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
|
||||
$Log$
|
||||
Revision 1.8 2000/01/05 08:20:39 markster
|
||||
Version 0.1.9 from FTP
|
||||
Revision 1.11 2000/01/05 08:20:39 markster
|
||||
Version 0.1.12 from FTP
|
||||
|
||||
Revision 1.2 2000/01/05 08:20:39 markster
|
||||
Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -29,8 +29,8 @@ extern int irc2pc_(real *rc, real *pc, integer *order, real *gprime, real *g2pas
|
||||
/* IRC2PC Version 48 */
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -82,8 +82,8 @@ extern int irc2pc_(real *rc, real *pc, integer *order, real *gprime, real *g2pas
|
||||
|
||||
/* Arguments */
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
|
||||
$Log$
|
||||
Revision 1.8 2000/01/05 08:20:39 markster
|
||||
Version 0.1.9 from FTP
|
||||
Revision 1.11 2000/01/05 08:20:39 markster
|
||||
Version 0.1.12 from FTP
|
||||
|
||||
Revision 1.2 2000/01/05 08:20:39 markster
|
||||
Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -29,8 +29,8 @@ extern int ivfilt_(real *lpbuf, real *ivbuf, integer *len, integer *nsamp, real
|
||||
/* IVFILT Version 48 */
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
|
||||
$Log$
|
||||
Revision 1.8 2000/01/05 00:20:06 markster
|
||||
Version 0.1.9 from FTP
|
||||
Revision 1.11 2000/01/05 00:20:06 markster
|
||||
Version 0.1.12 from FTP
|
||||
|
||||
Revision 1.1 2000/01/05 00:20:06 markster
|
||||
Add broken lpc10 code... It's not too far from working I don't think...
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
|
||||
$Log$
|
||||
Revision 1.8 2000/01/05 08:20:39 markster
|
||||
Version 0.1.9 from FTP
|
||||
Revision 1.11 2000/01/05 08:20:39 markster
|
||||
Version 0.1.12 from FTP
|
||||
|
||||
Revision 1.2 2000/01/05 08:20:39 markster
|
||||
Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -58,8 +58,8 @@ static integer c__10 = 10;
|
||||
/* ***************************************************************** */
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -113,8 +113,8 @@ static integer c__10 = 10;
|
||||
real rms;
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -147,8 +147,8 @@ static integer c__10 = 10;
|
||||
/* Frame size, Prediction order, Pitch period */
|
||||
/* Arguments */
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
|
||||
$Log$
|
||||
Revision 1.8 2000/01/05 08:20:39 markster
|
||||
Version 0.1.9 from FTP
|
||||
Revision 1.11 2000/01/05 08:20:39 markster
|
||||
Version 0.1.12 from FTP
|
||||
|
||||
Revision 1.2 2000/01/05 08:20:39 markster
|
||||
Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -50,8 +50,8 @@ static integer c__10 = 10;
|
||||
/* ***************************************************************** */
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -109,8 +109,8 @@ static integer c__10 = 10;
|
||||
|
||||
/* Arguments */
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
|
||||
$Log$
|
||||
Revision 1.8 2000/01/05 08:20:39 markster
|
||||
Version 0.1.9 from FTP
|
||||
Revision 1.11 2000/01/05 08:20:39 markster
|
||||
Version 0.1.12 from FTP
|
||||
|
||||
Revision 1.2 2000/01/05 08:20:39 markster
|
||||
Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -45,8 +45,8 @@ struct {
|
||||
/* ***************************************************************** */
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -71,8 +71,8 @@ struct {
|
||||
{
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -97,8 +97,8 @@ struct {
|
||||
/* LPC Configuration parameters: */
|
||||
/* Frame size, Prediction order, Pitch period */
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
|
||||
$Log$
|
||||
Revision 1.8 2000/01/05 08:20:39 markster
|
||||
Version 0.1.9 from FTP
|
||||
Revision 1.11 2000/01/05 08:20:39 markster
|
||||
Version 0.1.12 from FTP
|
||||
|
||||
Revision 1.2 2000/01/05 08:20:39 markster
|
||||
Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -29,8 +29,8 @@ extern int lpfilt_(real *inbuf, real *lpbuf, integer *len, integer *nsamp);
|
||||
/* LPFILT Version 55 */
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
|
||||
$Log$
|
||||
Revision 1.8 2000/01/05 08:20:39 markster
|
||||
Version 0.1.9 from FTP
|
||||
Revision 1.11 2000/01/05 08:20:39 markster
|
||||
Version 0.1.12 from FTP
|
||||
|
||||
Revision 1.2 2000/01/05 08:20:39 markster
|
||||
Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -29,8 +29,8 @@ extern integer median_(integer *d1, integer *d2, integer *d3);
|
||||
/* MEDIAN Version 45G */
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
|
||||
$Log$
|
||||
Revision 1.8 2000/01/05 08:20:39 markster
|
||||
Version 0.1.9 from FTP
|
||||
Revision 1.11 2000/01/05 08:20:39 markster
|
||||
Version 0.1.12 from FTP
|
||||
|
||||
Revision 1.2 2000/01/05 08:20:39 markster
|
||||
Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -29,8 +29,8 @@ extern int mload_(integer *order, integer *awins, integer *awinf, real *speech,
|
||||
/* MLOAD Version 48 */
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
|
||||
$Log$
|
||||
Revision 1.8 2000/01/05 08:20:39 markster
|
||||
Version 0.1.9 from FTP
|
||||
Revision 1.11 2000/01/05 08:20:39 markster
|
||||
Version 0.1.12 from FTP
|
||||
|
||||
Revision 1.2 2000/01/05 08:20:39 markster
|
||||
Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -41,8 +41,8 @@ static real c_b2 = 1.f;
|
||||
/* ONSET Version 49 */
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -143,8 +143,8 @@ static real c_b2 = 1.f;
|
||||
|
||||
/* Arguments */
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
|
||||
$Log$
|
||||
Revision 1.8 2000/01/05 08:20:39 markster
|
||||
Version 0.1.9 from FTP
|
||||
Revision 1.11 2000/01/05 08:20:39 markster
|
||||
Version 0.1.12 from FTP
|
||||
|
||||
Revision 1.2 2000/01/05 08:20:39 markster
|
||||
Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -37,8 +37,8 @@ extern int pitsyn_(integer *order, integer *voice, integer *pitch, real *rms, re
|
||||
/* PITSYN Version 53 */
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -143,8 +143,8 @@ extern int pitsyn_(integer *order, integer *voice, integer *pitch, real *rms, re
|
||||
|
||||
/* Arguments */
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
|
||||
$Log$
|
||||
Revision 1.8 2001/04/12 21:27:53 markster
|
||||
Version 0.1.9 from FTP
|
||||
Revision 1.11 2001/04/12 21:27:53 markster
|
||||
Version 0.1.12 from FTP
|
||||
|
||||
Revision 1.3 2001/04/12 21:27:53 markh
|
||||
app_record now supports wildcards of sort so your output file is not overwritten every time it's run. File.h got a documentation update on the ast_fileexists to include the return call. Watch out for the placea.c placev.c code, it's updates have not been tested yet. Just a few parenthesis to make it compile nicer on newer gcc versions with all the -W flags set.
|
||||
@@ -32,8 +32,8 @@ extern int placea_(integer *ipitch, integer *voibuf, integer *obound, integer *a
|
||||
/* PLACEA Version 48 */
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2001/04/12 21:27:53 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2001/04/12 21:27:53 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.3 2001/04/12 21:27:53 markh
|
||||
/* app_record now supports wildcards of sort so your output file is not overwritten every time it's run. File.h got a documentation update on the ast_fileexists to include the return call. Watch out for the placea.c placev.c code, it's updates have not been tested yet. Just a few parenthesis to make it compile nicer on newer gcc versions with all the -W flags set.
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
|
||||
$Log$
|
||||
Revision 1.8 2001/04/12 21:27:53 markster
|
||||
Version 0.1.9 from FTP
|
||||
Revision 1.11 2001/04/12 21:27:53 markster
|
||||
Version 0.1.12 from FTP
|
||||
|
||||
Revision 1.3 2001/04/12 21:27:53 markh
|
||||
app_record now supports wildcards of sort so your output file is not overwritten every time it's run. File.h got a documentation update on the ast_fileexists to include the return call. Watch out for the placea.c placev.c code, it's updates have not been tested yet. Just a few parenthesis to make it compile nicer on newer gcc versions with all the -W flags set.
|
||||
@@ -32,8 +32,8 @@ extern int placev_(integer *osbuf, integer *osptr, integer *oslen, integer *obou
|
||||
/* PLACEV Version 48 */
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2001/04/12 21:27:53 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2001/04/12 21:27:53 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.3 2001/04/12 21:27:53 markh
|
||||
/* app_record now supports wildcards of sort so your output file is not overwritten every time it's run. File.h got a documentation update on the ast_fileexists to include the return call. Watch out for the placea.c placev.c code, it's updates have not been tested yet. Just a few parenthesis to make it compile nicer on newer gcc versions with all the -W flags set.
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
|
||||
$Log$
|
||||
Revision 1.8 2000/01/05 08:20:39 markster
|
||||
Version 0.1.9 from FTP
|
||||
Revision 1.11 2000/01/05 08:20:39 markster
|
||||
Version 0.1.12 from FTP
|
||||
|
||||
Revision 1.2 2000/01/05 08:20:39 markster
|
||||
Some OSS fixes and a few lpc changes to make it actually work
|
||||
@@ -29,8 +29,8 @@ extern int preemp_(real *inbuf, real *pebuf, integer *nsamp, real *coef, real *z
|
||||
/* PREEMP Version 55 */
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.11 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.12 from FTP
|
||||
*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user