mirror of
https://github.com/asterisk/asterisk.git
synced 2026-01-20 08:44:06 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
836e861dde | ||
|
|
04ec7f1429 | ||
|
|
35e505b579 |
41
BUGS
41
BUGS
@@ -2,43 +2,10 @@
|
||||
these bugs are in asterisk, and sometimes they relate to the products
|
||||
that asterisk uses.
|
||||
|
||||
* The translator API may introduce warble in the case of going in both
|
||||
directions, but I haven't verified that. The trouble should only enter
|
||||
in the case of mismatched frame lengths.
|
||||
|
||||
* In general Asterisk is a very new program, and there are liable to be
|
||||
many bugs yet to be discovered, so if you think you've found one, please
|
||||
be sure to report it.
|
||||
|
||||
* When you flip to call waiting on a tormenta channel while you have a
|
||||
three way call up, the parties in the three way cannot hear one another
|
||||
in the general case.
|
||||
|
||||
======================================================================
|
||||
Short report on the voicemail system
|
||||
======================================================================
|
||||
Stuff We Need:
|
||||
|
||||
-Date/Time (conversion on the fly for different locales)
|
||||
-A more fleshed/emphasized Main Menu
|
||||
-Mailbox Options
|
||||
-useful for allowing user to set certain options
|
||||
-Notification of new vs. old messages
|
||||
-Notification of first and last messages (old and new)
|
||||
and a return to the Main Menu @ the end
|
||||
**-Better handling of lack of user input, specifically...
|
||||
infinite loops...
|
||||
currently found in: vm-instructions
|
||||
vm-msginstruct
|
||||
System MUST disconnect user for inactivity
|
||||
-Mid message menu w/
|
||||
pause/unpause
|
||||
seeking
|
||||
callback option
|
||||
option to get caller's number if available
|
||||
option to leave message directly on caller's voicemail
|
||||
if he/she has account on system
|
||||
-Also redesign the End Of Message Menu
|
||||
-Efficienty Question...
|
||||
Better to always rename msgs to being @ 0001
|
||||
or...
|
||||
Better to append new msgs numerically @ the
|
||||
end and use software to traverse them in
|
||||
order...saving cpu cycles on renaming files
|
||||
..could get messy w/ lots of users
|
||||
|
||||
88
CHANGES
88
CHANGES
@@ -1,91 +1,3 @@
|
||||
Asterisk 0.1.9
|
||||
-- Implement IAX quelching
|
||||
-- Allow Caller*ID to be overridden and suggested
|
||||
-- Configure defaults to use IAXTEL
|
||||
-- Allow remote dialplan polling via IAX
|
||||
-- Eliminate ast_longest_extension
|
||||
-- Implement dialplan request/reply
|
||||
-- Let peers have allow/disallow for codecs
|
||||
-- Change allow/deny to permit/deny in IAX
|
||||
-- Allow dialplan entries to match Caller*ID as well
|
||||
-- Added AGI (Asterisk Gateway Interface) scripting interface (app_agi)
|
||||
-- Added chan_zap for zapata telephony kernel interface, removed chan_tor
|
||||
-- Add convenience functions
|
||||
-- Fix race condition in channel hangup
|
||||
-- Fix memory leaks in both asterisk and iax frame allocations
|
||||
-- Add "iax show stats" command and -DTRACE_FRAMES (for frame tracing)
|
||||
-- Add DISA application (Thanks to Jim Dixon)
|
||||
-- Add IAX transfer support
|
||||
-- Add URL and HTML transmission
|
||||
-- Add application for sending images
|
||||
-- Add RedHat RPM spec file and build capability
|
||||
-- Fix GSM WAV file format bug
|
||||
-- Move ignorepat to main dialplan
|
||||
-- Add ability to specificy TOS bits in IAX
|
||||
-- Allow username:password in IAX strings
|
||||
-- Updates to PhoneJack interface
|
||||
-- Allow "servermail" in voicemail.conf to override e-mail in "from" line
|
||||
-- Add 'skip' option to app_playback
|
||||
-- Reject IAX calls on unknown extensions
|
||||
-- Fix version stuff
|
||||
Asterisk 0.1.8
|
||||
-- Keep track of version information
|
||||
-- Add -f to cause Asterisk not to fork
|
||||
-- Keep important information in voicemail .txt file
|
||||
-- Adtran Voice over Frame Relay updates
|
||||
-- Implement option setting/querying of channel drivers
|
||||
-- IAX performance improvements and protocol fixes
|
||||
-- Substantial enhancement of console channel driver
|
||||
-- Add IAX registration. Now IAX can dynamically register
|
||||
-- Add flash-hook transfer on tormenta channels
|
||||
-- Added Three Way Calling on tormenta channels
|
||||
-- Start on concept of zombie channel
|
||||
-- Add Call Waiting CallerID
|
||||
-- Keep track of who registeres contexts, includes, and extensions
|
||||
-- Added Call Waiting(tm), *67, *70, and *82 codes
|
||||
-- Move parked calls into "parkedcalls" context by default
|
||||
-- Allow dialplan to be displayed
|
||||
-- Allow "=>" instead of just "=" to make instantiation clearer
|
||||
-- Asterisk forks if called with no arguments
|
||||
-- Add remote control by running asterisk -vvvc
|
||||
-- Adjust verboseness with "set verbose" now
|
||||
-- No longer requires libaudiofile
|
||||
-- Install beep
|
||||
-- Make PBX Config module reload extensions on SIGHUP
|
||||
-- Allow modules to be reloaded when SIGHUP is received
|
||||
-- Variables now contain line numbers
|
||||
-- Make dialer send in band signalling
|
||||
-- Add record application
|
||||
-- Added PRI signalling to Tormenta driver
|
||||
-- Allow use of BYEXTENSION in "Goto"
|
||||
-- Allow adjustment of gains on tormenta channels
|
||||
-- Added raw PCM file format support
|
||||
-- Add U-law translator
|
||||
-- Fix DTMF handling in bridge code
|
||||
-- Fix access control with IAX
|
||||
* Asterisk 0.1.7
|
||||
-- Update configuration files and add some missing sounds
|
||||
-- Added ability to include one context in another
|
||||
-- Rewrite of PBX switching
|
||||
-- Major mods to dialler application
|
||||
-- Added Caller*ID spill reception
|
||||
-- Added Dialogic VOX file format support
|
||||
-- Added ADPCM Codec
|
||||
-- Add Tormenta driver (RBS signalling)
|
||||
-- Add Caller*ID spill creation
|
||||
-- Rewrite of translation layer entirely
|
||||
-- Add ability to run PBX without additional thread
|
||||
* Asterisk 0.1.6
|
||||
-- Make app_dial handle a lack of translators smoothly
|
||||
-- Add ISDN4Linux support -- dtmf is weird...
|
||||
-- Minor bug fixes
|
||||
* Asterisk 0.1.5
|
||||
-- Fix a small mistake in IAX
|
||||
-- Fix the QuickNet driver to work with newer cards
|
||||
* Asterisk 0.1.4
|
||||
-- Update VoFR some more
|
||||
-- Fix the QuickNet driver to work with LineJack
|
||||
-- Add ability to pass images for IAX.
|
||||
* Asterisk 0.1.3
|
||||
-- Update VoFR for latest sangoma code
|
||||
-- Update QuickNet Driver
|
||||
|
||||
7
CREDITS
7
CREDITS
@@ -6,13 +6,6 @@ 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.
|
||||
|
||||
=== OTHER SOURCE CODE IN ASTERISK ===
|
||||
|
||||
I did not implement the codecs in asterisk. Here is the copyright on the
|
||||
|
||||
125
Makefile
125
Makefile
@@ -14,10 +14,7 @@
|
||||
|
||||
.EXPORT_ALL_VARIABLES:
|
||||
|
||||
INSTALL_PREFIX=
|
||||
|
||||
MODULES_DIR=$(INSTALL_PREFIX)/usr/lib/asterisk/modules
|
||||
AGI_DIR=$(INSTALL_PREFIX)/var/lib/asterisk/agi-bin
|
||||
MODULES_DIR=/usr/lib/asterisk/modules
|
||||
|
||||
# Pentium Pro Optimize
|
||||
#PROC=i686
|
||||
@@ -26,22 +23,12 @@ PROC=i586
|
||||
|
||||
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 -Werror -Wmissing-prototypes -Wmissing-declarations -O6 $(DEBUG) $(INCLUDE) -D_REENTRANT
|
||||
CFLAGS+=$(shell if $(CC) -march=$(PROC) -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=$(PROC)"; fi)
|
||||
ASTERISKVERSION=$(shell if [ -f .version ]; then cat .version; fi)
|
||||
RPMVERSION=$(shell sed 's/[-\/:]/_/g' .version)
|
||||
CFLAGS+=-DASTERISK_VERSION=\"$(ASTERISKVERSION)\"
|
||||
# Optional debugging parameters
|
||||
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
|
||||
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
|
||||
CFLAGS+=$(shell [ ! -f /usr/include/linux/if_wanpipe.h ] && echo " -DOLD_SANGOMA_API")
|
||||
SUBDIRS=channels pbx apps codecs formats
|
||||
LIBS=-ldl -lpthread -lreadline #-lefence
|
||||
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 asterisk.o
|
||||
CC=gcc
|
||||
INSTALL=install
|
||||
|
||||
@@ -52,17 +39,12 @@ _all: all
|
||||
@echo " + running: +"
|
||||
@echo " + +"
|
||||
@echo " + make install +"
|
||||
@echo " + +"
|
||||
@echo " +-------------------------------------------+"
|
||||
|
||||
all: asterisk subdirs
|
||||
|
||||
_version:
|
||||
if [ -d CVS ] && ! [ -f .version ]; then echo "CVS-`date +"%D-%T"`" > .version; fi
|
||||
|
||||
build.h:
|
||||
./make_build_h
|
||||
|
||||
asterisk: _version build.h $(OBJS)
|
||||
asterisk: $(OBJS)
|
||||
gcc -o asterisk -rdynamic $(OBJS) $(LIBS)
|
||||
|
||||
subdirs:
|
||||
@@ -71,39 +53,27 @@ subdirs:
|
||||
clean:
|
||||
for x in $(SUBDIRS); do $(MAKE) -C $$x clean || exit 1 ; done
|
||||
rm -f *.o *.so asterisk
|
||||
rm -f build.h
|
||||
|
||||
datafiles: all
|
||||
mkdir -p $(INSTALL_PREFIX)/var/lib/asterisk/sounds/digits
|
||||
mkdir -p /var/lib/asterisk/sounds/digits
|
||||
for x in sounds/digits/*; do \
|
||||
install $$x $(INSTALL_PREFIX)/var/lib/asterisk/sounds/digits ; \
|
||||
install $$x /var/lib/asterisk/sounds/digits ; \
|
||||
done
|
||||
for x in sounds/vm-* sounds/transfer* sounds/pbx-* sounds/ss-* sounds/beep* sounds/dir-*; do \
|
||||
install $$x $(INSTALL_PREFIX)/var/lib/asterisk/sounds ; \
|
||||
for x in sounds/vm-* sounds/transfer* ; do \
|
||||
install $$x /var/lib/asterisk/sounds ; \
|
||||
done
|
||||
mkdir -p $(INSTALL_PREFIX)/var/lib/asterisk/images
|
||||
for x in images/*.jpg; do \
|
||||
install $$x $(INSTALL_PREFIX)/var/lib/asterisk/images ; \
|
||||
done
|
||||
mkdir -p $(AGI_DIR)
|
||||
|
||||
install: all datafiles
|
||||
install: all
|
||||
mkdir -p $(MODULES_DIR)
|
||||
mkdir -p $(INSTALL_PREFIX)/usr/sbin
|
||||
install -m 755 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
|
||||
rm -f $(INSTALL_PREFIX)/var/lib/asterisk/sounds/vm
|
||||
mkdir -p $(INSTALL_PREFIX)/var/spool/asterisk/vm
|
||||
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
|
||||
( cd $(INSTALL_PREFIX)/var/lib/asterisk/sounds ; ln -s ../../../spool/asterisk/vm . )
|
||||
install -d /usr/include/asterisk
|
||||
install include/asterisk/*.h /usr/include/asterisk
|
||||
rm -f /var/lib/asterisk/sounds/vm
|
||||
mkdir -p /var/spool/asterisk/vm
|
||||
rm -f /usr/lib/asterisk/modules/chan_ixj.so
|
||||
mkdir -p /var/lib/asterisk/sounds
|
||||
( cd /var/lib/asterisk/sounds ; ln -s ../../../spool/asterisk/vm . )
|
||||
@echo " +---- Asterisk Installation Complete -------+"
|
||||
@echo " + +"
|
||||
@echo " + YOU MUST READ THE SECURITY DOCUMENT +"
|
||||
@echo " + +"
|
||||
@echo " + Asterisk has successfully been installed. +"
|
||||
@echo " + If you would like to install the sample +"
|
||||
@echo " + configuration files (overwriting any +"
|
||||
@@ -111,56 +81,25 @@ install: all datafiles
|
||||
@echo " + +"
|
||||
@echo " + make samples +"
|
||||
@echo " + +"
|
||||
@echo " +----------------- or ---------------------+"
|
||||
@echo " + +"
|
||||
@echo " + You can go ahead and install the asterisk +"
|
||||
@echo " + program documentation now or later run: +"
|
||||
@echo " + +"
|
||||
@echo " + make progdocs +"
|
||||
@echo " + +"
|
||||
@echo " + **Note** This requires that you have +"
|
||||
@echo " + doxygen installed on your local system +"
|
||||
@echo " +-------------------------------------------+"
|
||||
@echo " +-------------------------------------------+"
|
||||
|
||||
samples: all datafiles
|
||||
mkdir -p $(INSTALL_PREFIX)/etc/asterisk
|
||||
mkdir -p /etc/asterisk
|
||||
for x in configs/*.sample; do \
|
||||
if [ -f $(INSTALL_PREFIX)/etc/asterisk/`basename $$x .sample` ]; then \
|
||||
mv -f $(INSTALL_PREFIX)/etc/asterisk/`basename $$x .sample` $(INSTALL_PREFIX)/etc/asterisk/`basename $$x .sample`.old ; \
|
||||
if [ -f /etc/asterisk/`basename $$x .sample` ]; then \
|
||||
mv -f /etc/asterisk/`basename $$x .sample` /etc/asterisk/`basename $$x .sample`.old ; \
|
||||
fi ; \
|
||||
install $$x $(INSTALL_PREFIX)/etc/asterisk/`basename $$x .sample` ;\
|
||||
install $$x /etc/asterisk/`basename $$x .sample` ;\
|
||||
done
|
||||
for x in sounds/demo-*; do \
|
||||
install $$x $(INSTALL_PREFIX)/var/lib/asterisk/sounds; \
|
||||
install $$x /var/lib/asterisk/sounds; \
|
||||
done
|
||||
mkdir -p $(INSTALL_PREFIX)/var/spool/asterisk/vm/1234/INBOX
|
||||
:> $(INSTALL_PREFIX)/var/lib/asterisk/sounds/vm/1234/unavail.gsm
|
||||
mkdir -p /var/spool/asterisk/vm/1234/INBOX
|
||||
:> /var/lib/asterisk/sounds/vm/1234/unavail.gsm
|
||||
for x in vm-theperson digits/1 digits/2 digits/3 digits/4 vm-isunavail; do \
|
||||
cat $(INSTALL_PREFIX)/var/lib/asterisk/sounds/$$x.gsm >> $(INSTALL_PREFIX)/var/lib/asterisk/sounds/vm/1234/unavail.gsm ; \
|
||||
cat /var/lib/asterisk/sounds/$$x.gsm >> /var/lib/asterisk/sounds/vm/1234/unavail.gsm ; \
|
||||
done
|
||||
:> $(INSTALL_PREFIX)/var/lib/asterisk/sounds/vm/1234/busy.gsm
|
||||
:> /var/lib/asterisk/sounds/vm/1234/busy.gsm
|
||||
for x in vm-theperson digits/1 digits/2 digits/3 digits/4 vm-isonphone; do \
|
||||
cat $(INSTALL_PREFIX)/var/lib/asterisk/sounds/$$x.gsm >> $(INSTALL_PREFIX)/var/lib/asterisk/sounds/vm/1234/busy.gsm ; \
|
||||
cat /var/lib/asterisk/sounds/$$x.gsm >> /var/lib/asterisk/sounds/vm/1234/busy.gsm ; \
|
||||
done
|
||||
|
||||
mailbox:
|
||||
./addmailbox
|
||||
|
||||
|
||||
rpm: __rpm
|
||||
|
||||
__rpm: _version
|
||||
rm -rf /tmp/asterisk ; \
|
||||
mkdir -p /tmp/asterisk/redhat/RPMS/i386 ; \
|
||||
make INSTALL_PREFIX=/tmp/asterisk install ; \
|
||||
make INSTALL_PREFIX=/tmp/asterisk samples ; \
|
||||
mkdir -p /tmp/asterisk/etc/rc.d/init.d ; \
|
||||
cp -f redhat/asterisk /tmp/asterisk/etc/rc.d/init.d/ ; \
|
||||
cp -f redhat/rpmrc /tmp/asterisk/ ; \
|
||||
cp -f redhat/rpmmacros /tmp/asterisk/ ; \
|
||||
sed "s/Version:/Version: $(RPMVERSION)/g" redhat/asterisk.spec > /tmp/asterisk/asterisk.spec ; \
|
||||
rpm --rcfile /usr/lib/rpm/rpmrc:/tmp/asterisk/rpmrc -bb /tmp/asterisk/asterisk.spec ; \
|
||||
mv /tmp/asterisk/redhat/RPMS/i386/asterisk* ./ ; \
|
||||
rm -rf /tmp/asterisk
|
||||
|
||||
progdocs:
|
||||
doxygen asterisk-ng-doxygen
|
||||
|
||||
84
README
84
README
@@ -1,11 +1,7 @@
|
||||
The Asterisk Open Source PBX
|
||||
by Mark Spencer <markster@linux-support.net>
|
||||
Copyright (C) 2001, Linux Support Services, Inc.
|
||||
Copyright (C) 1999, Mark Spencer
|
||||
================================================================
|
||||
* SECURITY
|
||||
It is imperative that you read and fully understand the contents of
|
||||
the SECURITY file before you attempt to configure an Asterisk server.
|
||||
|
||||
* WHAT IS ASTERISK
|
||||
Asterisk is an Open Source PBX and telephony toolkit. It is, in a
|
||||
sense, middleware between Internet and telephony channels on the bottom,
|
||||
@@ -14,27 +10,7 @@ on the project itself, please visit the Asterisk home page at:
|
||||
|
||||
http://www.asteriskpbx.com
|
||||
|
||||
* LICENSING
|
||||
Asterisk is distributed under GNU General Public License. The GPL also
|
||||
must apply to all loadable modules as well, except as defined below.
|
||||
|
||||
Linux Support Services, Inc. retains copyright to all of the core
|
||||
Asterisk system, and therefore can grant, at its sole discression, the
|
||||
ability for companies, individuals, or organizations to create proprietary
|
||||
or Open Source (but non-GPL'd) modules which may be dynamically linked at
|
||||
runtime with the portions of Asterisk which fall under our copyright
|
||||
umbrella, or are distributed under more flexible licenses than GPL. At
|
||||
this time (5/21/2001) the only component of Asterisk which is covered
|
||||
under GPL and not under our Copyright is the Xing MP3 decoder.
|
||||
|
||||
If you wish to use our code in other GPL programs, don't worry -- there
|
||||
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).
|
||||
|
||||
If you have any questions, whatsoever, regarding our licensing policy,
|
||||
please contact us.
|
||||
|
||||
* REQUIRED COMPONENTS
|
||||
|
||||
== Linux ==
|
||||
@@ -42,17 +18,24 @@ please contact us.
|
||||
Linux OS, although it may be portable to other UNIX-like operating systems
|
||||
as well.
|
||||
|
||||
== libaudiofile ==
|
||||
|
||||
If you want to use format_wav module, then you need a very recent
|
||||
version of libaudiofile (at least version 0.2.0, or you can apply the
|
||||
included patch. RPMS for the patched libaudiofile are available at:
|
||||
ftp://ftp.asteriskpbx.com/pub/asterisk/support
|
||||
|
||||
|
||||
* GETTING STARTED
|
||||
|
||||
First, be sure you've got supported hardware. To use Asterisk right now,
|
||||
you will need one of the following:
|
||||
First, be sure you've installed the required libaudiofile upgrade if
|
||||
you want to use the non-GSM WAV format. Next, 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
|
||||
* Full Duplex Sound Card supported by Linux
|
||||
* ISDN4Linux compatible ISDN card
|
||||
* Tormenta Dual T1 card (www.bsdtelephony.com.mx)
|
||||
|
||||
Assuming you have one of these (most likely the third) you're ready to
|
||||
proceed:
|
||||
@@ -71,10 +54,13 @@ Finally, you can launch Asterisk with:
|
||||
|
||||
./asterisk -vvvc
|
||||
|
||||
If you get an error about unresolved symbols, install the updated
|
||||
libaudiofile (available at ftp://ftp.asteriskpbx.com/pub/asterisk/support
|
||||
|
||||
You'll see a bunch of verbose messages fly by your screen as Asterisk
|
||||
initializes (that's the "very very verbose" mode). When it's ready, if
|
||||
you specified the "c" then you'll get a command line console, that looks
|
||||
like this:
|
||||
like this:
|
||||
|
||||
*CLI>
|
||||
|
||||
@@ -89,44 +75,6 @@ won't work right (not yet).
|
||||
Feel free to look over the configuration files in /etc/asterisk, where
|
||||
you'll find a lot of information about what you can do with Asterisk.
|
||||
|
||||
* ABOUT CONFIGURATION FILES
|
||||
|
||||
All Asterisk configuration files share a common format. Comments are
|
||||
delimited by ';' (since '#' of course, being a DTMF digit, may occur in
|
||||
many places). A configuration file is divided into sections whose names
|
||||
appear in []'s. Each section typically contains two types of statements,
|
||||
those of the form 'variable = value', and those of the form 'object =>
|
||||
parameters'. Internally the use of '=' and '=>' is exactly the same, so
|
||||
they're used only to help make the configuration file easier to
|
||||
understand, and do not affect how it is actually parsed.
|
||||
|
||||
Entries of the form 'variable=value' set the value of some parameter in
|
||||
asterisk. For example, in tormenta.conf, one might specify:
|
||||
|
||||
switchtype=national
|
||||
|
||||
In order to indicate to Asterisk that the switch they are connecting to is
|
||||
of the type "national". In general, the parameter will apply to
|
||||
instantiations which occur below its specification. For example, if the
|
||||
configuration file read:
|
||||
|
||||
switchtype = national
|
||||
channel => 1-4
|
||||
channel => 10-12
|
||||
switchtype = dms100
|
||||
channel => 25-47
|
||||
|
||||
Then, the "national" switchtype would be applied to channels one through
|
||||
four and channels 10 through 12, whereas the "dms100" switchtype would
|
||||
apply to channels 25 through 47.
|
||||
|
||||
The "object => parameters" instantiates an object with the given
|
||||
parameters. For example, the line "channel => 25-47" creates objects for
|
||||
the channels 25 through 47 of the tormenta card, obtaining the settings
|
||||
from the variables specified above.
|
||||
|
||||
* MORE INFORMATION
|
||||
|
||||
Finally, you may wish to visit the web site and join the mailing list if
|
||||
you're interested in getting more information.
|
||||
|
||||
|
||||
38
SECURITY
38
SECURITY
@@ -1,38 +0,0 @@
|
||||
==== Security Notes with Asterisk ====
|
||||
|
||||
PLEASE READ THE FOLLOWING IMPORTANT SECURITY RELATED INFORMATION.
|
||||
IMPROPER CONFIGURATION OF ASTERISK COULD ALLOW UNAUTHORIZED USE OF YOUR
|
||||
FACILITIES, POTENTIALLY INCURRING SUBSTANTIAL CHARGES.
|
||||
|
||||
First and foremost remember this:
|
||||
|
||||
USE THE EXTENSION CONTEXTS TO ISOLATE OUTGOING OR TOLL SERVICES FROM ANY
|
||||
INCOMING CONNECTIONS.
|
||||
|
||||
You should consider that if any channel, incoming line, etc can enter an
|
||||
extension context that it has the capability of accessing any extension
|
||||
within that context.
|
||||
|
||||
Therefore, you should NOT allow access to outgoing or toll services in
|
||||
contexts that are accessible (especially without a password) from incoming
|
||||
channels, be they IAX channels, FX or other trunks, or even untrusted
|
||||
stations within you network. In particular, never ever put outgoing toll
|
||||
services in the "default" context. To make things easier, you can include
|
||||
the "default" context within other private contexts by using:
|
||||
|
||||
include => default
|
||||
|
||||
in the appropriate section. A well designed PBX might look like this:
|
||||
|
||||
[longdistance]
|
||||
exten => _91NXXNXXXXXX,1,Dial,Tor/g2/BYEXTENSION
|
||||
include => local
|
||||
|
||||
[local]
|
||||
exten => _9NXXNXXX,1,Dial,Tor/g2/BYEXTENSION
|
||||
include => default
|
||||
|
||||
[default]
|
||||
exten => 6123,Dial,Tor/1
|
||||
|
||||
|
||||
20
addmailbox
20
addmailbox
@@ -1,20 +0,0 @@
|
||||
#!/bin/sh
|
||||
VMHOME=/var/spool/asterisk/vm
|
||||
SNDHOME=/var/lib/asterisk/sounds
|
||||
echo -n "Enter mailbox number: "
|
||||
read mailbox
|
||||
mkdir -p ${VMHOME}/${mailbox}
|
||||
mkdir -p ${VMHOME}/${mailbox}/INBOX
|
||||
cat ${SNDHOME}/vm-theperson.gsm > ${VMHOME}/${mailbox}/unavail.gsm
|
||||
cat ${SNDHOME}/vm-theperson.gsm > ${VMHOME}/${mailbox}/busy.gsm
|
||||
cat ${SNDHOME}/vm-extension.gsm > ${VMHOME}/${mailbox}/greet.gsm
|
||||
nums=`echo $mailbox | sed 's/./ \0/g'`
|
||||
for x in $nums; do
|
||||
cat ${SNDHOME}/digits/${x}.gsm >> ${VMHOME}/${mailbox}/unavail.gsm
|
||||
cat ${SNDHOME}/digits/${x}.gsm >> ${VMHOME}/${mailbox}/busy.gsm
|
||||
cat ${SNDHOME}/digits/${x}.gsm >> ${VMHOME}/${mailbox}/greet.gsm
|
||||
done
|
||||
|
||||
cat ${SNDHOME}/vm-isunavail.gsm >> ${VMHOME}/${mailbox}/unavail.gsm
|
||||
cat ${SNDHOME}/vm-isonphone.gsm >> ${VMHOME}/${mailbox}/busy.gsm
|
||||
|
||||
27
agi/Makefile
27
agi/Makefile
@@ -1,27 +0,0 @@
|
||||
#
|
||||
# Asterisk -- A telephony toolkit for Linux.
|
||||
#
|
||||
# Makefile for PBX frontends (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
|
||||
#
|
||||
|
||||
AGIS=agi-test.agi
|
||||
|
||||
CFLAGS+=
|
||||
|
||||
all: $(AGIS)
|
||||
|
||||
install: all
|
||||
for x in $(AGIS); do $(INSTALL) -m 755 $$x $(AGI_DIR) ; done
|
||||
|
||||
clean:
|
||||
rm -f *.so *.o look
|
||||
|
||||
%.so : %.o
|
||||
$(CC) -shared -Xlinker -x -o $@ $<
|
||||
@@ -1,73 +0,0 @@
|
||||
#!/usr/bin/perl
|
||||
$|=1;
|
||||
while(<STDIN>) {
|
||||
chomp;
|
||||
last unless length($_);
|
||||
if (/^agi_(\w+)\:\s+(.*)$/) {
|
||||
$AGI{$1} = $2;
|
||||
}
|
||||
}
|
||||
|
||||
print STDERR "AGI Environment Dump:\n";
|
||||
foreach $i (sort keys %AGI) {
|
||||
print STDERR " -- $i = $AGI{$i}\n";
|
||||
}
|
||||
|
||||
sub checkresult {
|
||||
my ($res) = @_;
|
||||
my $retval;
|
||||
$tests++;
|
||||
chomp $res;
|
||||
if ($res =~ /^200/) {
|
||||
$res =~ /result=(-?\d+)/;
|
||||
if (!length($1)) {
|
||||
print STDERR "FAIL ($res)\n";
|
||||
$fail++;
|
||||
} else {
|
||||
print STDERR "PASS ($1)\n";
|
||||
$pass++;
|
||||
}
|
||||
} else {
|
||||
print STDERR "FAIL (unexpected result '$res')\n";
|
||||
$fail++;
|
||||
}
|
||||
}
|
||||
|
||||
print STDERR "1. Testing 'sendfile'...";
|
||||
print "STREAM FILE beep \"\"\n";
|
||||
$result = <STDIN>;
|
||||
checkresult($result);
|
||||
|
||||
print STDERR "2. Testing 'sendtext'...";
|
||||
print "SEND TEXT \"hello world\"\n";
|
||||
$result = <STDIN>;
|
||||
checkresult($result);
|
||||
|
||||
print STDERR "3. Testing 'sendimage'...";
|
||||
print "SEND IMAGE asterisk-image\n";
|
||||
$result = <STDIN>;
|
||||
checkresult($result);
|
||||
|
||||
print STDERR "4. Testing 'saynumber'...";
|
||||
print "SAY NUMBER 192837465 \"\"\n";
|
||||
$result = <STDIN>;
|
||||
checkresult($result);
|
||||
|
||||
print STDERR "5. Testing 'waitdtmf'...";
|
||||
print "WAIT FOR DIGIT 1000\n";
|
||||
$result = <STDIN>;
|
||||
checkresult($result);
|
||||
|
||||
print STDERR "6. Testing 'record'...";
|
||||
print "RECORD FILE testagi gsm 1234 3000\n";
|
||||
$result = <STDIN>;
|
||||
checkresult($result);
|
||||
|
||||
print STDERR "6a. Testing 'record' playback...";
|
||||
print "STREAM FILE testagi \"\"\n";
|
||||
$result = <STDIN>;
|
||||
checkresult($result);
|
||||
|
||||
print STDERR "================== Complete ======================\n";
|
||||
print STDERR "$tests tests completed, $pass passed, $fail failed\n";
|
||||
print STDERR "==================================================\n";
|
||||
43
app.c
43
app.c
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Channel Management
|
||||
*
|
||||
* 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/channel.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/app.h>
|
||||
|
||||
/* set timeout to 0 for "standard" timeouts. Set timeout to -1 for
|
||||
"ludicrous time" (essentially never times out) */
|
||||
int ast_app_getdata(struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout)
|
||||
{
|
||||
int res,to,fto;
|
||||
if (prompt) {
|
||||
res = ast_streamfile(c, prompt, c->language);
|
||||
if (res < 0)
|
||||
return res;
|
||||
}
|
||||
fto = 6000;
|
||||
to = 2000;
|
||||
if (timeout > 0) fto = to = timeout;
|
||||
if (timeout < 0) fto = to = 1000000000;
|
||||
res = ast_readstring(c, s, maxlen, to, fto, "#");
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -11,29 +11,17 @@
|
||||
# the GNU General Public License
|
||||
#
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
CFLAGS+=
|
||||
|
||||
all: $(APPS)
|
||||
|
||||
clean:
|
||||
rm -f *.so *.o look
|
||||
rm -f *.so *.o
|
||||
|
||||
%.so : %.o
|
||||
$(CC) -shared -Xlinker -x -o $@ $<
|
||||
|
||||
install: all
|
||||
for x in $(APPS); do $(INSTALL) -m 755 $$x $(MODULES_DIR) ; done
|
||||
|
||||
app_todd.o: app_todd.c
|
||||
gcc -pipe -O6 -g -Iinclude -I../include -D_REENTRANT -march=i586 -DDO_CRASH -DDEBUG_THREADS -c -o app_todd.o app_todd.c
|
||||
|
||||
app_todd.so: app_todd.o
|
||||
$(CC) -shared -Xlinker -x -o $@ $< -L/usr/local/ssl/lib -lssl -lcrypto
|
||||
|
||||
|
||||
look: look.c
|
||||
gcc -pipe -O6 -g look.c -o look -lncurses
|
||||
|
||||
809
apps/app_agi.c
809
apps/app_agi.c
@@ -1,809 +0,0 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Asterisk Gateway Interface
|
||||
*
|
||||
* 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/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/time.h>
|
||||
#include <asterisk/cli.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/image.h>
|
||||
#include <asterisk/say.h>
|
||||
#include "../asterisk.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#define MAX_ARGS 128
|
||||
|
||||
/* Recycle some stuff from the CLI interface */
|
||||
#define fdprintf ast_cli
|
||||
|
||||
typedef struct agi_command {
|
||||
/* Null terminated list of the words of the command */
|
||||
char *cmda[AST_MAX_CMD_LEN];
|
||||
/* Handler for the command (fd for output, # of arguments, argument list).
|
||||
Returns RESULT_SHOWUSAGE for improper arguments */
|
||||
int (*handler)(struct ast_channel *chan, int fd, int argc, char *argv[]);
|
||||
/* Summary of the command (< 60 characters) */
|
||||
char *summary;
|
||||
/* Detailed usage information */
|
||||
char *usage;
|
||||
} agi_command;
|
||||
|
||||
static char *tdesc = "Asterisk Gateway Interface (AGI)";
|
||||
|
||||
static char *app = "AGI";
|
||||
|
||||
static char *synopsis = "Executes an AGI compliant application";
|
||||
|
||||
static char *descrip =
|
||||
" AGI(command|args): Executes an Asterisk Gateway Interface compliant\n"
|
||||
"program on a channel. AGI allows Asterisk to launch external programs\n"
|
||||
"written in any language to control a telephony channel, play audio,\n"
|
||||
"read DTMF digits, etc. by communicating with the AGI protocol on stdin\n"
|
||||
"and stdout. Returns -1 on hangup or if application requested hangup, or\n"
|
||||
"0 on non-hangup exit.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
#define TONE_BLOCK_SIZE 200
|
||||
|
||||
static float loudness = 8192.0;
|
||||
|
||||
unsigned char linear2ulaw(short sample);
|
||||
static void make_tone_block(unsigned char *data, float f1, int *x);
|
||||
|
||||
static void make_tone_block(unsigned char *data, float f1, int *x)
|
||||
{
|
||||
int i;
|
||||
float val;
|
||||
|
||||
for(i = 0; i < TONE_BLOCK_SIZE; i++)
|
||||
{
|
||||
val = loudness * sin((f1 * 2.0 * M_PI * (*x)++)/8000.0);
|
||||
data[i] = linear2ulaw((int)val);
|
||||
}
|
||||
/* wrap back around from 8000 */
|
||||
if (*x >= 8000) *x = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
static int launch_script(char *script, char *args, int *fds, int *opid)
|
||||
{
|
||||
char tmp[256];
|
||||
int pid;
|
||||
int toast[2];
|
||||
int fromast[2];
|
||||
int x;
|
||||
if (script[0] != '/') {
|
||||
snprintf(tmp, sizeof(tmp), "%s/%s", AST_AGI_DIR, script);
|
||||
script = tmp;
|
||||
}
|
||||
if (pipe(toast)) {
|
||||
ast_log(LOG_WARNING, "Unable to create toast pipe: %s\n",strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (pipe(fromast)) {
|
||||
ast_log(LOG_WARNING, "unable to create fromast pipe: %s\n", strerror(errno));
|
||||
close(toast[0]);
|
||||
close(toast[1]);
|
||||
return -1;
|
||||
}
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (!pid) {
|
||||
/* Redirect stdin and out */
|
||||
dup2(fromast[0], STDIN_FILENO);
|
||||
dup2(toast[1], STDOUT_FILENO);
|
||||
/* Close everything but stdin/out/error */
|
||||
for (x=STDERR_FILENO + 1;x<1024;x++)
|
||||
close(x);
|
||||
/* Execute script */
|
||||
execl(script, script, args, NULL);
|
||||
ast_log(LOG_WARNING, "Failed to execute '%s': %s\n", script, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Launched AGI Script %s\n", script);
|
||||
fds[0] = toast[0];
|
||||
fds[1] = fromast[1];
|
||||
/* close what we're not using in the parent */
|
||||
close(toast[1]);
|
||||
close(fromast[0]);
|
||||
*opid = pid;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static void setup_env(struct ast_channel *chan, char *request, int fd)
|
||||
{
|
||||
/* Print initial environment, with agi_request always being the first
|
||||
thing */
|
||||
fdprintf(fd, "agi_request: %s\n", request);
|
||||
fdprintf(fd, "agi_channel: %s\n", chan->name);
|
||||
fdprintf(fd, "agi_language: %s\n", chan->language);
|
||||
fdprintf(fd, "agi_type: %s\n", chan->type);
|
||||
|
||||
/* ANI/DNIS */
|
||||
fdprintf(fd, "agi_callerid: %s\n", chan->callerid ? chan->callerid : "");
|
||||
fdprintf(fd, "agi_dnid: %s\n", chan->dnid ? chan->dnid : "");
|
||||
|
||||
/* Context information */
|
||||
fdprintf(fd, "agi_context: %s\n", chan->context);
|
||||
fdprintf(fd, "agi_extension: %s\n", chan->exten);
|
||||
fdprintf(fd, "agi_priority: %d\n", chan->priority);
|
||||
|
||||
/* End with empty return */
|
||||
fdprintf(fd, "\n");
|
||||
}
|
||||
|
||||
static int handle_waitfordigit(struct ast_channel *chan, int fd, int argc, char *argv[])
|
||||
{
|
||||
int res;
|
||||
int to;
|
||||
if (argc != 4)
|
||||
return RESULT_SHOWUSAGE;
|
||||
if (sscanf(argv[3], "%i", &to) != 1)
|
||||
return RESULT_SHOWUSAGE;
|
||||
res = ast_waitfordigit(chan, to);
|
||||
fdprintf(fd, "200 result=%d\n", res);
|
||||
if (res >= 0)
|
||||
return RESULT_SUCCESS;
|
||||
else
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
|
||||
static int handle_sendtext(struct ast_channel *chan, int fd, int argc, char *argv[])
|
||||
{
|
||||
int res;
|
||||
if (argc != 3)
|
||||
return RESULT_SHOWUSAGE;
|
||||
res = ast_sendtext(chan, argv[2]);
|
||||
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)
|
||||
res = 0;
|
||||
fdprintf(fd, "200 result=%d\n", res);
|
||||
if (res >= 0)
|
||||
return RESULT_SUCCESS;
|
||||
else
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
|
||||
static int handle_streamfile(struct ast_channel *chan, int fd, int argc, char *argv[])
|
||||
{
|
||||
int res;
|
||||
if (argc != 4)
|
||||
return RESULT_SHOWUSAGE;
|
||||
res = ast_streamfile(chan, argv[2],chan->language);
|
||||
if (res) {
|
||||
fdprintf(fd, "200 result=%d\n", res);
|
||||
if (res >= 0)
|
||||
return RESULT_SHOWUSAGE;
|
||||
else
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
res = ast_waitstream(chan, argv[3]);
|
||||
|
||||
fdprintf(fd, "200 result=%d\n", res);
|
||||
if (res >= 0)
|
||||
return RESULT_SUCCESS;
|
||||
else
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
|
||||
static int handle_saynumber(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_number(chan, num, chan->language);
|
||||
fdprintf(fd, "200 result=%d\n", res);
|
||||
if (res >= 0)
|
||||
return RESULT_SUCCESS;
|
||||
else
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
|
||||
int ast_app_getdata(struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout);
|
||||
|
||||
static int handle_getdata(struct ast_channel *chan, int fd, int argc, char *argv[])
|
||||
{
|
||||
int res;
|
||||
char data[50];
|
||||
int max;
|
||||
int timeout;
|
||||
|
||||
if (argc < 3)
|
||||
return RESULT_SHOWUSAGE;
|
||||
if (argc >= 4) timeout = atoi(argv[3]); else timeout = 0;
|
||||
if (argc >= 5) max = atoi(argv[4]); else max = 50;
|
||||
res = ast_app_getdata(chan, argv[2], data, max, timeout);
|
||||
if (res == 1)
|
||||
fdprintf(fd, "200 result=%s (timeout)\n", data);
|
||||
else
|
||||
fdprintf(fd, "200 result=%s\n", data);
|
||||
if (res >= 0)
|
||||
return RESULT_SUCCESS;
|
||||
else
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
|
||||
static int handle_setcontext(struct ast_channel *chan, int fd, int argc, char *argv[])
|
||||
{
|
||||
|
||||
if (argc != 3)
|
||||
return RESULT_SHOWUSAGE;
|
||||
strncpy(chan->context, argv[2], sizeof(chan->context));
|
||||
fdprintf(fd, "200 result=0\n");
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static int handle_setextension(struct ast_channel *chan, int fd, int argc, char **argv)
|
||||
{
|
||||
if (argc != 3)
|
||||
return RESULT_SHOWUSAGE;
|
||||
strncpy(chan->exten, argv[2], sizeof(chan->exten));
|
||||
fdprintf(fd, "200 result=0\n");
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static int handle_setpriority(struct ast_channel *chan, int fd, int argc, char **argv)
|
||||
{
|
||||
int pri;
|
||||
if (argc != 3)
|
||||
return RESULT_SHOWUSAGE;
|
||||
if (sscanf(argv[2], "%i", &pri) != 1)
|
||||
return RESULT_SHOWUSAGE;
|
||||
chan->priority = pri - 1;
|
||||
fdprintf(fd, "200 result=0\n");
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static int ms_diff(struct timeval *tv1, struct timeval *tv2)
|
||||
{
|
||||
int ms;
|
||||
|
||||
ms = (tv1->tv_sec - tv2->tv_sec) * 1000;
|
||||
ms += (tv1->tv_usec - tv2->tv_usec) / 1000;
|
||||
return(ms);
|
||||
}
|
||||
|
||||
static int handle_recordfile(struct ast_channel *chan, int fd, int argc, char *argv[])
|
||||
{
|
||||
struct ast_filestream *fs;
|
||||
struct ast_frame *f,wf;
|
||||
struct timeval tv, start, lastout, now, notime = { 0,0 } ;
|
||||
fd_set readfds;
|
||||
unsigned char tone_block[TONE_BLOCK_SIZE];
|
||||
int res = -1;
|
||||
int ms,i,j;
|
||||
|
||||
if (argc < 6)
|
||||
return RESULT_SHOWUSAGE;
|
||||
if (sscanf(argv[5], "%i", &ms) != 1)
|
||||
return RESULT_SHOWUSAGE;
|
||||
|
||||
if (argc > 6) { /* if to beep */
|
||||
i = 0;
|
||||
lastout.tv_sec = lastout.tv_usec = 0;
|
||||
for(j = 0; j < 13; j++)
|
||||
{
|
||||
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 = tone_block;
|
||||
wf.datalen = TONE_BLOCK_SIZE;
|
||||
/* make this tone block */
|
||||
make_tone_block(tone_block,1000.0,&i);
|
||||
wf.timelen = wf.datalen / 8;
|
||||
if (ast_write(chan, &wf)) {
|
||||
fdprintf(fd, "200 result=%d (hangup)\n", 0);
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
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;
|
||||
f = ast_read(chan);
|
||||
if (!f) {
|
||||
fdprintf(fd, "200 result=%d (hangup)\n", 0);
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
switch(f->frametype) {
|
||||
case AST_FRAME_DTMF:
|
||||
if (strchr(argv[4], f->subclass)) {
|
||||
/* This is an interrupting chracter */
|
||||
fdprintf(fd, "200 result=%d (dtmf)\n", f->subclass);
|
||||
ast_frfree(f);
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
break;
|
||||
case AST_FRAME_VOICE:
|
||||
break; /* throw it away */
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
/* suck in 5 voice frames to make up for echo of beep, etc */
|
||||
for(i = 0; i < 5; i++) {
|
||||
f = ast_read(chan);
|
||||
if (!f) {
|
||||
fdprintf(fd, "200 result=%d (hangup)\n", 0);
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
switch(f->frametype) {
|
||||
case AST_FRAME_DTMF:
|
||||
if (strchr(argv[4], f->subclass)) {
|
||||
/* This is an interrupting chracter */
|
||||
fdprintf(fd, "200 result=%d (dtmf)\n", f->subclass);
|
||||
ast_frfree(f);
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
break;
|
||||
case AST_FRAME_VOICE:
|
||||
break; /* throw it away */
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fs = ast_writefile(argv[2], argv[3], NULL, O_CREAT | O_TRUNC | O_WRONLY, 0, 0644);
|
||||
if (!fs) {
|
||||
fdprintf(fd, "200 result=%d (writefile)\n", res);
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
gettimeofday(&start, NULL);
|
||||
gettimeofday(&tv, NULL);
|
||||
while ((ms < 0) || (((tv.tv_sec - start.tv_sec) * 1000 + (tv.tv_usec - start.tv_usec)/1000) < ms)) {
|
||||
res = ast_waitfor(chan, -1);
|
||||
if (res < 0) {
|
||||
ast_closestream(fs);
|
||||
fdprintf(fd, "200 result=%d (waitfor)\n", res);
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
f = ast_read(chan);
|
||||
if (!f) {
|
||||
fdprintf(fd, "200 result=%d (hangup)\n", 0);
|
||||
ast_closestream(fs);
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
switch(f->frametype) {
|
||||
case AST_FRAME_DTMF:
|
||||
if (strchr(argv[4], f->subclass)) {
|
||||
/* This is an interrupting chracter */
|
||||
fdprintf(fd, "200 result=%d (dtmf)\n", f->subclass);
|
||||
ast_closestream(fs);
|
||||
ast_frfree(f);
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
break;
|
||||
case AST_FRAME_VOICE:
|
||||
ast_writestream(fs, f);
|
||||
break;
|
||||
};
|
||||
ast_frfree(f);
|
||||
gettimeofday(&tv, NULL);
|
||||
}
|
||||
fdprintf(fd, "200 result=%d (timeout)\n", 0);
|
||||
ast_closestream(fs);
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static char usage_waitfordigit[] =
|
||||
" Usage: WAIT FOR DIGIT <timeout>\n"
|
||||
" Waits up to 'timeout' seconds for channel to receive a DTMF digit.\n"
|
||||
" Returns -1 on channel failure, 0 if no digit is received in the timeout, or\n"
|
||||
" the numerical value of the ascii of the digit if one is received. Use -1\n"
|
||||
" for the timeout value if you desire the call to block indefinitely.\n";
|
||||
|
||||
static char usage_sendtext[] =
|
||||
" Usage: SEND TEXT \"<text to send>\"\n"
|
||||
" Sends the given text on a channel. Most channels do not support the\n"
|
||||
" transmission of text. Returns 0 if text is sent, or if the channel does not\n"
|
||||
" support text transmission. Returns -1 only on error/hangup. Text\n"
|
||||
" consisting of greater than one word should be placed in quotes since the\n"
|
||||
" command only accepts a single argument.\n";
|
||||
|
||||
static char usage_sendimage[] =
|
||||
" Usage: SEND IMAGE <image>\n"
|
||||
" Sends the given image on a channel. Most channels do not support the\n"
|
||||
" transmission of images. Returns 0 if image is sent, or if the channel does not\n"
|
||||
" support image transmission. Returns -1 only on error/hangup. Image names\n"
|
||||
" should not include extensions.\n";
|
||||
|
||||
static char usage_streamfile[] =
|
||||
" Usage: STREAM FILE <filename> <escape digits>\n"
|
||||
" Send the given file, allowing playback to be interrupted by the given\n"
|
||||
" digits, if any. Use double quotes for the digits if you wish none to be\n"
|
||||
" permitted. Returns 0 if playback completes without a digit being pressed, or\n"
|
||||
" the ASCII numerical value of the digit if one was pressed, or -1 on error or\n"
|
||||
" if the channel was disconnected. Remember, the file extension must not be\n"
|
||||
" included in the filename.\n";
|
||||
|
||||
static char usage_saynumber[] =
|
||||
" Usage: SAY NUMBER <number> <escape digits>\n"
|
||||
" Say a given number, 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"
|
||||
"from the channel at the other end.\n";
|
||||
|
||||
static char usage_setcontext[] =
|
||||
" Usage: SET CONTEXT <desired context>\n"
|
||||
" Sets the context for continuation upon exiting the application.\n";
|
||||
|
||||
static char usage_setextension[] =
|
||||
" Usage: SET EXTENSION <new extension>\n"
|
||||
" Changes the extension for continuation upon exiting the application.\n";
|
||||
|
||||
static char usage_setpriority[] =
|
||||
" Usage: SET PRIORITY <num>\n"
|
||||
" Changes the priority for continuation upon exiting the application.\n";
|
||||
|
||||
static char usage_recordfile[] =
|
||||
" Usage: RECORD FILE <filename> <format> <escape digits> <timeout> [BEEP]\n"
|
||||
" Record to a file until a given dtmf digit in the sequence is received\n"
|
||||
" Returns -1 on hangup or error. The format will specify what kind of file\n"
|
||||
" will be recorded. The timeout is the maximum record time in milliseconds, or\n"
|
||||
" -1 for no timeout\n";
|
||||
|
||||
agi_command commands[] = {
|
||||
{ { "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 },
|
||||
{ { "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", "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 },
|
||||
{ { "set", "extension", NULL }, handle_setextension, "Changes channel extension", usage_setextension },
|
||||
{ { "set", "priority", NULL }, handle_setpriority, "Prioritizes the channel", usage_setpriority },
|
||||
{ { "record", "file", NULL }, handle_recordfile, "Records to a given file", usage_recordfile }
|
||||
};
|
||||
|
||||
static agi_command *find_command(char *cmds[])
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
int match;
|
||||
for (x=0;x < sizeof(commands) / sizeof(commands[0]);x++) {
|
||||
/* start optimistic */
|
||||
match = 1;
|
||||
for (y=0;match && cmds[y]; y++) {
|
||||
/* If there are no more words in the command (and we're looking for
|
||||
an exact match) or there is a difference between the two words,
|
||||
then this is not a match */
|
||||
if (!commands[x].cmda[y])
|
||||
break;
|
||||
if (strcasecmp(commands[x].cmda[y], cmds[y]))
|
||||
match = 0;
|
||||
}
|
||||
/* If more words are needed to complete the command then this is not
|
||||
a candidate (unless we're looking for a really inexact answer */
|
||||
if (commands[x].cmda[y])
|
||||
match = 0;
|
||||
if (match)
|
||||
return &commands[x];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int parse_args(char *s, int *max, char *argv[])
|
||||
{
|
||||
int x=0;
|
||||
int quoted=0;
|
||||
int escaped=0;
|
||||
int whitespace=1;
|
||||
char *cur;
|
||||
|
||||
cur = s;
|
||||
while(*s) {
|
||||
switch(*s) {
|
||||
case '"':
|
||||
/* If it's escaped, put a literal quote */
|
||||
if (escaped)
|
||||
goto normal;
|
||||
else
|
||||
quoted = !quoted;
|
||||
if (quoted && whitespace) {
|
||||
/* If we're starting a quote, coming off white space start a new word, too */
|
||||
argv[x++] = cur;
|
||||
whitespace=0;
|
||||
}
|
||||
escaped = 0;
|
||||
break;
|
||||
case ' ':
|
||||
case '\t':
|
||||
if (!quoted && !escaped) {
|
||||
/* If we're not quoted, mark this as whitespace, and
|
||||
end the previous argument */
|
||||
whitespace = 1;
|
||||
*(cur++) = '\0';
|
||||
} else
|
||||
/* Otherwise, just treat it as anything else */
|
||||
goto normal;
|
||||
break;
|
||||
case '\\':
|
||||
/* If we're escaped, print a literal, otherwise enable escaping */
|
||||
if (escaped) {
|
||||
goto normal;
|
||||
} else {
|
||||
escaped=1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
normal:
|
||||
if (whitespace) {
|
||||
if (x >= MAX_ARGS -1) {
|
||||
ast_log(LOG_WARNING, "Too many arguments, truncating\n");
|
||||
break;
|
||||
}
|
||||
/* Coming off of whitespace, start the next argument */
|
||||
argv[x++] = cur;
|
||||
whitespace=0;
|
||||
}
|
||||
*(cur++) = *s;
|
||||
escaped=0;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
/* Null terminate */
|
||||
*(cur++) = '\0';
|
||||
argv[x] = NULL;
|
||||
*max = x;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int agi_handle_command(struct ast_channel *chan, int fd, char *buf)
|
||||
{
|
||||
char *argv[MAX_ARGS];
|
||||
int argc = 0;
|
||||
int res;
|
||||
agi_command *c;
|
||||
argc = MAX_ARGS;
|
||||
parse_args(buf, &argc, argv);
|
||||
#if 0
|
||||
{ int x;
|
||||
for (x=0;x<argc;x++)
|
||||
fprintf(stderr, "Got Arg%d: %s\n", x, argv[x]); }
|
||||
#endif
|
||||
c = find_command(argv);
|
||||
if (c) {
|
||||
res = c->handler(chan, fd, argc, argv);
|
||||
switch(res) {
|
||||
case RESULT_SHOWUSAGE:
|
||||
fdprintf(fd, "520-Invalid command syntax. Proper usage follows:\n");
|
||||
fdprintf(fd, c->usage);
|
||||
fdprintf(fd, "520 End of proper usage.\n");
|
||||
break;
|
||||
case RESULT_FAILURE:
|
||||
/* They've already given the failure. We've been hung up on so handle this
|
||||
appropriately */
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
fdprintf(fd, "510 Invalid or unknown command\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int run_agi(struct ast_channel *chan, char *request, int *fds, int pid)
|
||||
{
|
||||
struct ast_channel *c;
|
||||
int outfd;
|
||||
int ms;
|
||||
int returnstatus = 0;
|
||||
struct ast_frame *f;
|
||||
char buf[2048];
|
||||
FILE *readf;
|
||||
if (!(readf = fdopen(fds[0], "r"))) {
|
||||
ast_log(LOG_WARNING, "Unable to fdopen file descriptor\n");
|
||||
kill(pid, SIGHUP);
|
||||
return -1;
|
||||
}
|
||||
setlinebuf(readf);
|
||||
setup_env(chan, request, fds[1]);
|
||||
for (;;) {
|
||||
ms = -1;
|
||||
c = ast_waitfor_nandfds(&chan, 1, &fds[0], 1, NULL, &outfd, &ms);
|
||||
if (c) {
|
||||
/* Idle the channel until we get a command */
|
||||
f = ast_read(c);
|
||||
if (!f) {
|
||||
ast_log(LOG_DEBUG, "%s hungup\n", chan->name);
|
||||
returnstatus = -1;
|
||||
break;
|
||||
} else {
|
||||
ast_frfree(f);
|
||||
}
|
||||
} else if (outfd > -1) {
|
||||
if (!fgets(buf, sizeof(buf), readf)) {
|
||||
/* Program terminated */
|
||||
if (returnstatus)
|
||||
returnstatus = -1;
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "AGI Script %s completed, returning %d\n", request, returnstatus);
|
||||
/* No need to kill the pid anymore, since they closed us */
|
||||
pid = -1;
|
||||
break;
|
||||
}
|
||||
returnstatus |= agi_handle_command(chan, fds[1], buf);
|
||||
/* If the handle_command returns -1, we need to stop */
|
||||
if (returnstatus < 0) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "No channel, no fd?\n");
|
||||
returnstatus = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Notify process */
|
||||
if (pid > -1)
|
||||
kill(pid, SIGHUP);
|
||||
fclose(readf);
|
||||
return returnstatus;
|
||||
}
|
||||
|
||||
static int agi_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
char *args,*ringy;
|
||||
char tmp[256];
|
||||
int fds[2];
|
||||
int pid;
|
||||
if (!data || !strlen(data)) {
|
||||
ast_log(LOG_WARNING, "AGI requires an argument (script)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
strncpy(tmp, data, sizeof(tmp));
|
||||
strtok(tmp, "|");
|
||||
args = strtok(NULL, "|");
|
||||
ringy = strtok(NULL,"|");
|
||||
if (!args)
|
||||
args = "";
|
||||
LOCAL_USER_ADD(u);
|
||||
/* Answer if need be */
|
||||
if (chan->state != AST_STATE_UP) {
|
||||
if (ringy) { /* if for ringing first */
|
||||
/* a little ringy-dingy first */
|
||||
ast_indicate(chan, AST_CONTROL_RINGING);
|
||||
sleep(3);
|
||||
}
|
||||
if (ast_answer(chan)) {
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
res = launch_script(tmp, args, fds, &pid);
|
||||
if (!res) {
|
||||
res = run_agi(chan, tmp, fds, pid);
|
||||
close(fds[0]);
|
||||
close(fds[1]);
|
||||
}
|
||||
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, agi_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
#define CLIP 32635
|
||||
#define BIAS 0x84
|
||||
|
||||
unsigned char
|
||||
linear2ulaw(sample)
|
||||
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);
|
||||
}
|
||||
571
apps/app_dial.c
571
apps/app_dial.c
@@ -27,7 +27,6 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/signal.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
@@ -37,36 +36,11 @@ 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"
|
||||
"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"
|
||||
"which first answered. All other calls placed by the Dial app will be hunp up\n"
|
||||
"If a timeout is not specified, the Dial application will wait indefinitely\n"
|
||||
"until either one of the called channels answers, the user hangs up, or all\n"
|
||||
"channels return busy or error. In general, the dialler will return 0 if it\n"
|
||||
"was unable to place the call, or the timeout expired. However, if all\n"
|
||||
"channels were busy, and there exists an extension with priority n+101 (where\n"
|
||||
"n is the priority of the dialler instance), then it will be the next\n"
|
||||
"executed extension (this allows you to setup different behavior on busy from\n"
|
||||
"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"
|
||||
" 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;
|
||||
/* No more than 90 seconds parked before you do something with them */
|
||||
static int parkingtime = 90000;
|
||||
|
||||
/* Context for which parking is made accessible */
|
||||
static char parking_con[AST_MAX_EXTENSION] = "parkedcalls";
|
||||
static char parking_con[AST_MAX_EXTENSION] = "default";
|
||||
|
||||
/* Extension you type to park the call */
|
||||
static char parking_ext[AST_MAX_EXTENSION] = "700";
|
||||
@@ -118,7 +92,7 @@ static int park_call(struct ast_channel *chan, struct ast_channel *peer)
|
||||
int x;
|
||||
pu = malloc(sizeof(struct parkeduser));
|
||||
if (pu) {
|
||||
ast_pthread_mutex_lock(&parking_lock);
|
||||
pthread_mutex_lock(&parking_lock);
|
||||
for (x=parking_start;x<=parking_stop;x++) {
|
||||
cur = parkinglot;
|
||||
while(cur) {
|
||||
@@ -140,7 +114,7 @@ static int park_call(struct ast_channel *chan, struct ast_channel *peer)
|
||||
pu->priority = chan->priority;
|
||||
pu->next = parkinglot;
|
||||
parkinglot = pu;
|
||||
ast_pthread_mutex_unlock(&parking_lock);
|
||||
pthread_mutex_unlock(&parking_lock);
|
||||
/* Wake up the (presumably select()ing) thread */
|
||||
pthread_kill(parking_thread, SIGURG);
|
||||
if (option_verbose > 1)
|
||||
@@ -150,7 +124,7 @@ static int park_call(struct ast_channel *chan, struct ast_channel *peer)
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "No more parking spaces\n");
|
||||
free(pu);
|
||||
ast_pthread_mutex_unlock(&parking_lock);
|
||||
pthread_mutex_unlock(&parking_lock);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
@@ -166,7 +140,6 @@ static void *do_parking_thread(void *ignore)
|
||||
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);
|
||||
@@ -174,7 +147,7 @@ static void *do_parking_thread(void *ignore)
|
||||
for (;;) {
|
||||
ms = -1;
|
||||
max = -1;
|
||||
ast_pthread_mutex_lock(&parking_lock);
|
||||
pthread_mutex_lock(&parking_lock);
|
||||
pl = NULL;
|
||||
pu = parkinglot;
|
||||
gettimeofday(&tv, NULL);
|
||||
@@ -201,50 +174,41 @@ static void *do_parking_thread(void *ignore)
|
||||
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;
|
||||
} else if (FD_ISSET(pu->chan->fd, &rfds) || FD_ISSET(pu->chan->fd, &efds)) {
|
||||
/* 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);
|
||||
} 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 */
|
||||
}
|
||||
} else {
|
||||
/* Keep this one for next one */
|
||||
std: FD_SET(pu->chan->fd, &nrfds);
|
||||
FD_SET(pu->chan->fd, &nefds);
|
||||
/* Keep track of our longest wait */
|
||||
if ((tms < ms) || (ms < 0))
|
||||
ms = tms;
|
||||
if (pu->chan->fd > max)
|
||||
max = pu->chan->fd;
|
||||
pl = pu;
|
||||
pu = pu->next;
|
||||
}
|
||||
}
|
||||
ast_pthread_mutex_unlock(&parking_lock);
|
||||
pthread_mutex_unlock(&parking_lock);
|
||||
rfds = nrfds;
|
||||
efds = nefds;
|
||||
tv.tv_sec = ms / 1000;
|
||||
@@ -270,248 +234,246 @@ static void hanguptree(struct localuser *outgoing, struct ast_channel *exception
|
||||
}
|
||||
}
|
||||
|
||||
#define MAX 256
|
||||
|
||||
static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localuser *outgoing, int *to, int *allowredir)
|
||||
{
|
||||
fd_set rfds, efds;
|
||||
struct localuser *o;
|
||||
int found;
|
||||
int numlines;
|
||||
int sentringing = 0;
|
||||
int numbusies = 0;
|
||||
int orig = *to;
|
||||
struct timeval tv;
|
||||
struct ast_frame *f;
|
||||
struct ast_channel *peer = NULL;
|
||||
struct ast_channel *watchers[MAX];
|
||||
int pos;
|
||||
int single;
|
||||
struct ast_channel *winner;
|
||||
|
||||
single = (outgoing && !outgoing->next);
|
||||
|
||||
if (single) {
|
||||
/* If we are calling a single channel, make them compatible for in-band tone purpose */
|
||||
ast_channel_make_compatible(outgoing->chan, in);
|
||||
}
|
||||
|
||||
while(*to && !peer) {
|
||||
/* Watch all outgoing channels looking for an answer of some sort. */
|
||||
tv.tv_sec = *to / 1000;
|
||||
tv.tv_usec = (*to % 1000) * 1000;
|
||||
while((tv.tv_sec || tv.tv_usec) && !peer) {
|
||||
FD_ZERO(&rfds);
|
||||
FD_ZERO(&efds);
|
||||
/* Always watch the input fd */
|
||||
FD_SET(in->fd, &rfds);
|
||||
FD_SET(in->fd, &efds);
|
||||
o = outgoing;
|
||||
found = -1;
|
||||
pos = 1;
|
||||
numlines = 0;
|
||||
watchers[0] = in;
|
||||
while(o) {
|
||||
/* Keep track of important channels */
|
||||
if (o->stillgoing) {
|
||||
watchers[pos++] = o->chan;
|
||||
found = 1;
|
||||
/* Pay attention to this one */
|
||||
CHECK_BLOCKING(o->chan);
|
||||
FD_SET(o->chan->fd, &rfds);
|
||||
FD_SET(o->chan->fd, &efds);
|
||||
if (o->chan->fd > found)
|
||||
found = o->chan->fd;
|
||||
}
|
||||
o = o->next;
|
||||
numlines++;
|
||||
o = o->next;
|
||||
}
|
||||
if (found < 0) {
|
||||
/* If nobody is left, just go ahead and stop */
|
||||
if (found<0) {
|
||||
if (numlines == numbusies) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy at this time\n");
|
||||
/* See if there is a special busy message */
|
||||
if (ast_exists_extension(in, in->context, in->exten, in->priority + 101, in->callerid))
|
||||
if (ast_exists_extension(in, in->context, in->exten, in->priority + 101))
|
||||
in->priority+=100;
|
||||
} else {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_2 "No one is available to answer at this time\n");
|
||||
}
|
||||
*to = 0;
|
||||
break;
|
||||
}
|
||||
if (in->fd > found)
|
||||
found = in->fd;
|
||||
if (*to > -1)
|
||||
found = select(found + 1, &rfds, NULL, &efds, &tv);
|
||||
else
|
||||
found = select(found + 1, &rfds, NULL, &efds, NULL);
|
||||
if (found < 0) {
|
||||
ast_log(LOG_WARNING, "select failed, returned %d (%s)\n", errno, strerror(errno));
|
||||
*to = -1;
|
||||
o = outgoing;
|
||||
while(o) {
|
||||
if (o->stillgoing) {
|
||||
o->chan->blocking = 0;
|
||||
}
|
||||
o = o->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
winner = ast_waitfor_n(watchers, pos, to);
|
||||
o = outgoing;
|
||||
while(o) {
|
||||
if (o->chan == winner) {
|
||||
f = ast_read(winner);
|
||||
if (f) {
|
||||
if (f->frametype == AST_FRAME_CONTROL) {
|
||||
switch(f->subclass) {
|
||||
case AST_CONTROL_ANSWER:
|
||||
/* This is our guy if someone answered. */
|
||||
if (!peer) {
|
||||
if (o->stillgoing) {
|
||||
o->chan->blocking = 0;
|
||||
if (FD_ISSET(o->chan->fd, &rfds) || FD_ISSET(o->chan->fd, &efds)) {
|
||||
f = ast_read(o->chan);
|
||||
if (f) {
|
||||
if (f->frametype == AST_FRAME_CONTROL) {
|
||||
switch(f->subclass) {
|
||||
case AST_CONTROL_ANSWER:
|
||||
/* This is our guy if someone answered. */
|
||||
if (!peer) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
|
||||
peer = o->chan;
|
||||
*allowredir = o->allowredirect;
|
||||
}
|
||||
break;
|
||||
case AST_CONTROL_BUSY:
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
|
||||
peer = o->chan;
|
||||
*allowredir = o->allowredirect;
|
||||
ast_verbose( VERBOSE_PREFIX_3 "%s is busy\n", o->chan->name);
|
||||
o->stillgoing = 0;
|
||||
numbusies++;
|
||||
break;
|
||||
case AST_CONTROL_RINGING:
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
|
||||
break;
|
||||
case AST_CONTROL_OFFHOOK:
|
||||
/* Ignore going off hook */
|
||||
break;
|
||||
default:
|
||||
ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass);
|
||||
}
|
||||
break;
|
||||
case AST_CONTROL_BUSY:
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "%s is busy\n", o->chan->name);
|
||||
o->stillgoing = 0;
|
||||
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;
|
||||
numbusies++;
|
||||
break;
|
||||
case AST_CONTROL_RINGING:
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
|
||||
if (!sentringing) {
|
||||
ast_indicate(in, AST_CONTROL_RINGING);
|
||||
sentringing++;
|
||||
}
|
||||
break;
|
||||
case AST_CONTROL_OFFHOOK:
|
||||
/* Ignore going off hook */
|
||||
break;
|
||||
default:
|
||||
ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass);
|
||||
}
|
||||
} else if (single && (f->frametype == AST_FRAME_VOICE)) {
|
||||
if (ast_write(in, f))
|
||||
ast_log(LOG_WARNING, "Unable to forward frame\n");
|
||||
} else if (single && (f->frametype == AST_FRAME_IMAGE)) {
|
||||
if (ast_write(in, f))
|
||||
ast_log(LOG_WARNING, "Unable to forward image\n");
|
||||
ast_frfree(f);
|
||||
} else {
|
||||
o->stillgoing = 0;
|
||||
}
|
||||
ast_frfree(f);
|
||||
} else {
|
||||
o->stillgoing = 0;
|
||||
|
||||
}
|
||||
}
|
||||
o = o->next;
|
||||
}
|
||||
if (winner == in) {
|
||||
if (FD_ISSET(in->fd, &rfds) || FD_ISSET(in->fd, &efds)) {
|
||||
/* After unblocking the entirity of the list, check for the main channel */
|
||||
f = ast_read(in);
|
||||
#if 0
|
||||
if (f && (f->frametype != AST_FRAME_VOICE))
|
||||
printf("Frame type: %d, %d\n", f->frametype, f->subclass);
|
||||
else if (!f || (f->frametype != AST_FRAME_VOICE))
|
||||
printf("Hangup received on %s\n", in->name);
|
||||
#endif
|
||||
if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
|
||||
if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass = AST_CONTROL_HANGUP))) {
|
||||
/* Got hung up */
|
||||
*to=-1;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (!*to && (option_verbose > 2))
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig);
|
||||
|
||||
}
|
||||
if (!(tv.tv_sec || tv.tv_usec) && (option_verbose > 2))
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig);
|
||||
*to = 0;
|
||||
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_channel *cs[3];
|
||||
int to = -1, 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 (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);
|
||||
cs[0] = chan;
|
||||
cs[1] = peer;
|
||||
for (/* ever */;;) {
|
||||
who = ast_waitfor_n(cs, 2, &to);
|
||||
if (!who) {
|
||||
ast_log(LOG_WARNING, "Nobody there??\n");
|
||||
continue;
|
||||
}
|
||||
f = ast_read(who);
|
||||
if (!f || ((f->frametype == AST_FRAME_CONTROL) &&
|
||||
((f->subclass == AST_CONTROL_HANGUP) ||
|
||||
(f->subclass == AST_CONTROL_BUSY))))
|
||||
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;
|
||||
if ((f->frametype == AST_FRAME_VOICE) ||
|
||||
(f->frametype == AST_FRAME_DTMF) ||
|
||||
(f->frametype == AST_FRAME_TEXT)) {
|
||||
if ((f->frametype == AST_FRAME_DTMF) && (who == peer) && allowredirect &&
|
||||
(f->subclass == '#')) {
|
||||
if (f->subclass == '#') {
|
||||
memset(newext, 0, sizeof(newext));
|
||||
ptr = newext;
|
||||
len = ast_pbx_longest_extension(chan->context) + 1;
|
||||
if (len < ast_pbx_longest_extension("default") + 1)
|
||||
len = ast_pbx_longest_extension("default") + 1;
|
||||
|
||||
/* 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)
|
||||
if ((res=ast_streamfile(peer, "pbx-transfer", chan->language)))
|
||||
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;
|
||||
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 = ast_readstring(peer, ptr, len, 3000, 2000, "#");
|
||||
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)) {
|
||||
/* 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);
|
||||
res=0;
|
||||
break;
|
||||
} else if (ast_exists_extension(chan, "default", newext, 1)) {
|
||||
/* Set the channel's new extension, since it exists, using peer context */
|
||||
strncpy(chan->exten, newext, sizeof(chan->exten));
|
||||
strncpy(chan->context, "default", sizeof(chan->context));
|
||||
chan->priority = 0;
|
||||
ast_frfree(f);
|
||||
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;
|
||||
res = ast_streamfile(peer, "pbx-invalid", chan->language);
|
||||
if (res)
|
||||
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_waitstream(peer, AST_DIGIT_ANY);
|
||||
ast_stopstream(peer);
|
||||
res = 0;
|
||||
}
|
||||
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);
|
||||
#if 0
|
||||
ast_log(LOG_DEBUG, "Read from %s\n", who->name);
|
||||
#endif
|
||||
if (who == chan)
|
||||
ast_write(peer, f);
|
||||
else
|
||||
ast_write(chan, f);
|
||||
}
|
||||
ast_frfree(f);
|
||||
|
||||
} else
|
||||
ast_frfree(f);
|
||||
/* Swap who gets priority */
|
||||
cs[2] = cs[0];
|
||||
cs[0] = cs[1];
|
||||
cs[1] = cs[2];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -520,7 +482,7 @@ static int park_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
struct ast_channel *peer=NULL;
|
||||
struct ast_channel *peer=NULL, *nchan;
|
||||
struct parkeduser *pu, *pl=NULL;
|
||||
int park;
|
||||
if (!data) {
|
||||
@@ -529,7 +491,7 @@ static int park_exec(struct ast_channel *chan, void *data)
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
park = atoi((char *)data);
|
||||
ast_pthread_mutex_lock(&parking_lock);
|
||||
pthread_mutex_lock(&parking_lock);
|
||||
pu = parkinglot;
|
||||
while(pu) {
|
||||
if (pu->parkingnum == park) {
|
||||
@@ -541,23 +503,24 @@ static int park_exec(struct ast_channel *chan, void *data)
|
||||
}
|
||||
pu = pu->next;
|
||||
}
|
||||
ast_pthread_mutex_unlock(&parking_lock);
|
||||
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;
|
||||
}
|
||||
/* Build a translator if necessary */
|
||||
if (peer->format & chan->format)
|
||||
nchan = chan;
|
||||
else
|
||||
nchan = ast_translator_create(chan, peer->format, AST_DIRECTION_BOTH);
|
||||
/* 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);
|
||||
res = bridge_call(peer, nchan, 1);
|
||||
if (nchan != chan)
|
||||
ast_translator_destroy(nchan);
|
||||
/* Simulate the PBX hanging up */
|
||||
if (res != AST_PBX_KEEPALIVE)
|
||||
ast_hangup(peer);
|
||||
@@ -578,12 +541,11 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
struct localuser *u;
|
||||
char *info, *peers, *timeout, *tech, *number, *rest, *cur;
|
||||
struct localuser *outgoing=NULL, *tmp;
|
||||
struct ast_channel *peer;
|
||||
struct ast_channel *peer, *npeer;
|
||||
int to;
|
||||
int allowredir=0;
|
||||
char numsubst[AST_MAX_EXTENSION];
|
||||
char restofit[AST_MAX_EXTENSION];
|
||||
char *transfer = NULL;
|
||||
char *newnum;
|
||||
|
||||
if (!data) {
|
||||
@@ -595,81 +557,51 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
/* Parse our arguments XXX Check for failure XXX */
|
||||
info = malloc(strlen((char *)data) + AST_MAX_EXTENSION);
|
||||
if (!info) {
|
||||
ast_log(LOG_WARNING, "Out of memory\n");
|
||||
return -1;
|
||||
}
|
||||
strncpy(info, (char *)data, strlen((char *)data) + AST_MAX_EXTENSION);
|
||||
peers = info;
|
||||
if (peers) {
|
||||
timeout = strchr(info, '|');
|
||||
if (timeout) {
|
||||
*timeout = '\0';
|
||||
timeout++;
|
||||
transfer = strchr(timeout, '|');
|
||||
if (transfer) {
|
||||
*transfer = '\0';
|
||||
transfer++;
|
||||
}
|
||||
}
|
||||
} else
|
||||
timeout = NULL;
|
||||
if (!peers || !strlen(peers)) {
|
||||
peers = strtok(info, "|");
|
||||
if (!peers) {
|
||||
ast_log(LOG_WARNING, "Dial argument takes format (technology1/number1&technology2/number2...|optional timeout)\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
cur = peers;
|
||||
timeout = strtok(NULL, "|");
|
||||
rest = peers;
|
||||
do {
|
||||
cur = strtok(rest, "&");
|
||||
/* Remember where to start next time */
|
||||
rest = strchr(cur, '&');
|
||||
if (rest) {
|
||||
*rest = 0;
|
||||
rest++;
|
||||
}
|
||||
rest = strtok(NULL, "\128");
|
||||
/* Get a technology/[device:]number pair */
|
||||
tech = cur;
|
||||
number = strchr(tech, '/');
|
||||
tech = strtok(cur, "/");
|
||||
number = strtok(NULL, "&");
|
||||
if (!number) {
|
||||
ast_log(LOG_WARNING, "Dial argument takes format (technology1/[device:]number1&technology2/[device:]number2...|optional timeout)\n");
|
||||
goto out;
|
||||
}
|
||||
*number = '\0';
|
||||
number++;
|
||||
tmp = malloc(sizeof(struct localuser));
|
||||
if (!tmp) {
|
||||
ast_log(LOG_WARNING, "Out of memory\n");
|
||||
goto out;
|
||||
}
|
||||
if (transfer && (strchr(transfer, 't')))
|
||||
tmp->allowredirect = 1;
|
||||
else
|
||||
tmp->allowredirect = 0;
|
||||
tmp->allowredirect = 1;
|
||||
strncpy(numsubst, number, sizeof(numsubst));
|
||||
/* 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));
|
||||
snprintf(newnum, sizeof(numsubst) - (newnum - numsubst), "%s%s", chan->exten,restofit);
|
||||
/* By default, if we're dialing by extension, don't permit redirecting */
|
||||
tmp->allowredirect = 0;
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst);
|
||||
}
|
||||
/* Request the peer */
|
||||
tmp->chan = ast_request(tech, chan->nativeformats, numsubst);
|
||||
tmp->chan = ast_request(tech, chan->format, 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);
|
||||
free(tmp);
|
||||
cur = rest;
|
||||
continue;
|
||||
}
|
||||
tmp->chan->appl = "AppDial";
|
||||
tmp->chan->data = "(Outgoing Line)";
|
||||
if (tmp->chan->callerid)
|
||||
free(tmp->chan->callerid);
|
||||
if (chan->callerid)
|
||||
tmp->chan->callerid = strdup(chan->callerid);
|
||||
else
|
||||
tmp->chan->callerid = NULL;
|
||||
/* Place the call, but don't wait on the answer */
|
||||
res = ast_call(tmp->chan, numsubst, 0);
|
||||
if (res) {
|
||||
@@ -680,7 +612,6 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", numsubst);
|
||||
ast_hangup(tmp->chan);
|
||||
free(tmp);
|
||||
cur = rest;
|
||||
continue;
|
||||
} else
|
||||
if (option_verbose > 2)
|
||||
@@ -691,10 +622,8 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
tmp->stillgoing = -1;
|
||||
tmp->next = outgoing;
|
||||
outgoing = tmp;
|
||||
cur = rest;
|
||||
} while(cur);
|
||||
|
||||
if (timeout && strlen(timeout))
|
||||
} while(rest);
|
||||
if (timeout)
|
||||
to = atoi(timeout) * 1000;
|
||||
else
|
||||
to = -1;
|
||||
@@ -715,22 +644,14 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
conversation. */
|
||||
hanguptree(outgoing, peer);
|
||||
outgoing = NULL;
|
||||
/* Make sure channels are compatible */
|
||||
res = ast_channel_make_compatible(chan, peer);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
|
||||
ast_hangup(peer);
|
||||
return -1;
|
||||
}
|
||||
if (!strcmp(chan->type,"Zap")) {
|
||||
int x = 2;
|
||||
ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
|
||||
}
|
||||
if (!strcmp(peer->type,"Zap")) {
|
||||
int x = 2;
|
||||
ast_channel_setoption(peer,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
|
||||
}
|
||||
res = bridge_call(chan, peer, allowredir);
|
||||
/* Build a translator if necessary */
|
||||
if (peer->format & chan->format)
|
||||
npeer = peer;
|
||||
else
|
||||
npeer = ast_translator_create(peer, chan->format, AST_DIRECTION_BOTH);
|
||||
res = bridge_call(chan, npeer, allowredir);
|
||||
if (npeer != peer)
|
||||
ast_translator_destroy(npeer);
|
||||
ast_hangup(peer);
|
||||
}
|
||||
out:
|
||||
@@ -754,20 +675,17 @@ int load_module(void)
|
||||
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;
|
||||
}
|
||||
ast_log(LOG_ERROR, "Parking context '%s' does not exist\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);
|
||||
ast_add_extension2(con, 1, exten, 1, parkedcall, strdup(exten), free);
|
||||
}
|
||||
pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
|
||||
res = ast_register_application(parkedcall, park_exec, synopsis, descrip);
|
||||
res = ast_register_application(parkedcall, park_exec);
|
||||
if (!res)
|
||||
res = ast_register_application(app, dial_exec, synopsis, descrip);
|
||||
res = ast_register_application(app, dial_exec);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -782,8 +700,3 @@ int usecount(void)
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
@@ -28,15 +28,6 @@
|
||||
static char *tdesc = "Extension Directory";
|
||||
static char *app = "Directory";
|
||||
|
||||
static char *synopsis = "Provide directory of voicemail extensions";
|
||||
static char *descrip =
|
||||
" Directory(context): Presents the user with a directory of extensions from\n"
|
||||
"which they may select by name. The list of names and extensions is\n"
|
||||
"discovered from voicemail.conf. The context argument is required, and\n"
|
||||
"specifies the context in which to interpret the extensions\n. Returns 0\n"
|
||||
"unless the user hangs up. It also sets up the channel on exit to enter the\n"
|
||||
"extension the user selected.\n";
|
||||
|
||||
/* For simplicity, I'm keeping the format compatible with the voicemail config,
|
||||
but i'm open to suggestions for isolating it */
|
||||
|
||||
@@ -130,8 +121,7 @@ static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char *
|
||||
char fn[256];
|
||||
memset(ext, 0, sizeof(ext));
|
||||
ext[0] = digit;
|
||||
res = 0;
|
||||
if (ast_readstring(chan, ext + 1, NUMDIGITS, 3000, 3000, "#") < 0) res = -1;
|
||||
res = ast_readstring(chan, ext + 1, NUMDIGITS, 3000, 3000, "#");
|
||||
if (!res) {
|
||||
/* Search for all names which start with those digits */
|
||||
v = ast_variable_browse(cfg, context);
|
||||
@@ -258,7 +248,7 @@ int unload_module(void)
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, directory_exec, synopsis, descrip);
|
||||
return ast_register_application(app, directory_exec);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
@@ -272,8 +262,3 @@ int usecount(void)
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
401
apps/app_disa.c
401
apps/app_disa.c
@@ -1,401 +0,0 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* DISA -- Direct Inward System Access Application 6/20/2001
|
||||
*
|
||||
* Copyright (C) 2001, Linux Support Services, Inc.
|
||||
*
|
||||
* Jim Dixon <jim@lambdatel.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#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/ulaw.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#define TONE_BLOCK_SIZE 200
|
||||
|
||||
static char *tdesc = "DISA (Direct Inward System Access) Application";
|
||||
|
||||
static char *app = "DISA";
|
||||
|
||||
static char *synopsis = "DISA (Direct Inward System Access)";
|
||||
|
||||
static char *descrip =
|
||||
"DISA (Direct Inward System Access) -- Allows someone from outside\n"
|
||||
"the telephone switch (PBX) to obtain an \"internal\" system dialtone\n"
|
||||
"and to place calls from it as if they were placing a call from within\n"
|
||||
"the switch. A user calls a number that connects to the DISA application\n"
|
||||
"and is given dialtone. The user enters their passcode, followed by the\n"
|
||||
"pound sign (#). If the passcode is correct, the user is then given\n"
|
||||
"system dialtone on which a call may be placed. Obviously, this type\n"
|
||||
"of access has SERIOUS security implications, and GREAT care must be\n"
|
||||
"taken NOT to compromise your security.\n\n"
|
||||
"There is a possibility of accessing DISA without password. Simply\n"
|
||||
"exchange your password with no-password.\n\n"
|
||||
" Example: exten => s,1,DISA,no-password|local\n\n"
|
||||
"but be aware of using this for your security compromising.\n\n"
|
||||
"The arguments to this application (in extensions.conf) allow either\n"
|
||||
"specification of a single global password (that everyone uses), or\n"
|
||||
"individual passwords contained in a file. It also allow specification\n"
|
||||
"of the context on which the user will be dialing. If no context is\n"
|
||||
"specified, the DISA application defaults the context to \"disa\"\n"
|
||||
"presumably that a normal system will have a special context set up\n"
|
||||
"for DISA use with some or a lot of restrictions. The arguments are\n"
|
||||
"one of the following:\n\n"
|
||||
" numeric-passcode\n"
|
||||
" numeric-passcode|context\n"
|
||||
" full-pathname-of-file-that-contains-passcodes\n\n"
|
||||
"The file that contains the passcodes (if used) allows specification\n"
|
||||
"of either just a passcode (defaulting to the \"disa\" context, or\n"
|
||||
"passcode|context on each line of the file. The file may contain blank\n"
|
||||
"lines, or comments starting with \"#\" or \";\".\n\n"
|
||||
"If login is successful, the application parses the dialed number in\n"
|
||||
"the specified (or default) context, and returns 0 with the new extension\n"
|
||||
"context filled-in and the priority set to 1, so that the PBX may\n"
|
||||
"re-apply the routing tables to it and complete the call normally.";
|
||||
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static float loudness=8192.0;
|
||||
|
||||
int firstdigittimeout = 10000; /* 10 seconds first digit timeout */
|
||||
int digittimeout = 5000; /* 5 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)
|
||||
{
|
||||
int i;
|
||||
float val;
|
||||
|
||||
for(i = 0; i < TONE_BLOCK_SIZE; 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];
|
||||
}
|
||||
/* wrap back around from 8000 */
|
||||
if (*x >= 8000) *x = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
static int ms_diff(struct timeval *tv1, struct timeval *tv2)
|
||||
{
|
||||
int ms;
|
||||
|
||||
ms = (tv1->tv_sec - tv2->tv_sec) * 1000;
|
||||
ms += (tv1->tv_usec - tv2->tv_usec) / 1000;
|
||||
return(ms);
|
||||
}
|
||||
|
||||
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 *ourcontext;
|
||||
struct ast_frame *f,wf;
|
||||
fd_set readfds;
|
||||
int waitfor_notime;
|
||||
struct timeval notime = { 0,0 }, lastout, now, lastdigittime;
|
||||
FILE *fp;
|
||||
|
||||
if (ast_set_write_format(chan,AST_FORMAT_ULAW))
|
||||
{
|
||||
ast_log(LOG_WARNING, "Unable to set write format to Mu-law on %s\n",chan->name);
|
||||
return -1;
|
||||
}
|
||||
if (ast_set_read_format(chan,AST_FORMAT_ULAW))
|
||||
{
|
||||
ast_log(LOG_WARNING, "Unable to set read format to Mu-law on %s\n",chan->name);
|
||||
return -1;
|
||||
}
|
||||
lastout.tv_sec = lastout.tv_usec = 0;
|
||||
/* make block of silence */
|
||||
memset(sil_block,0x7f,TONE_BLOCK_SIZE);
|
||||
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));
|
||||
strtok(tmp, "|");
|
||||
ourcontext = strtok(NULL, "|");
|
||||
/* if context not specified, use "disa" */
|
||||
if (!ourcontext) ourcontext = "disa";
|
||||
LOCAL_USER_ADD(u);
|
||||
if (chan->state != AST_STATE_UP)
|
||||
{
|
||||
/* answer */
|
||||
ast_answer(chan);
|
||||
}
|
||||
i = k = x = 0; /* k is 0 for pswd entry, 1 for ext entry */
|
||||
exten[0] = 0;
|
||||
/* can we access DISA without password? */
|
||||
if (!strcasecmp(tmp, "no-password"))
|
||||
{
|
||||
k = 1;
|
||||
ast_log(LOG_DEBUG, "DISA no-password login success\n");
|
||||
}
|
||||
gettimeofday(&lastdigittime,NULL);
|
||||
for(;;)
|
||||
{
|
||||
gettimeofday(&now,NULL);
|
||||
/* if outa time, give em reorder */
|
||||
if (ms_diff(&now,&lastdigittime) >
|
||||
((k) ? digittimeout : firstdigittimeout))
|
||||
{
|
||||
ast_log(LOG_DEBUG,"DISA %s entry timeout on chan %s\n",
|
||||
((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;
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
/* if not DTMF, just do it again */
|
||||
if (f->frametype != AST_FRAME_DTMF)
|
||||
{
|
||||
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 */
|
||||
{
|
||||
if (!k) /* if in password state */
|
||||
{
|
||||
if (j == '#') /* end of password */
|
||||
{
|
||||
/* see if this is an integer */
|
||||
if (sscanf(tmp,"%d",&j) < 1)
|
||||
{ /* nope, it must be a filename */
|
||||
fp = fopen(tmp,"r");
|
||||
if (!fp)
|
||||
{
|
||||
ast_log(LOG_WARNING,"DISA password file %s not found on chan %s\n",tmp,chan->name);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
tmp[0] = 0;
|
||||
while(fgets(tmp,sizeof(tmp) - 1,fp))
|
||||
{
|
||||
if (!tmp[0]) continue;
|
||||
if (tmp[strlen(tmp) - 1] == '\n')
|
||||
tmp[strlen(tmp) - 1] = 0;
|
||||
if (!tmp[0]) continue;
|
||||
/* skip comments */
|
||||
if (tmp[0] == '#') continue;
|
||||
if (tmp[0] == ';') continue;
|
||||
strtok(tmp, "|");
|
||||
ourcontext = strtok(NULL, "|");
|
||||
/* password must be in valid format (numeric) */
|
||||
if (sscanf(tmp,"%d",&j) < 1) continue;
|
||||
/* if we got it */
|
||||
if (!strcmp(exten,tmp)) break;
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
/* compare the two */
|
||||
if (strcmp(exten,tmp))
|
||||
{
|
||||
ast_log(LOG_WARNING,"DISA on chan %s got bad password %s\n",chan->name,exten);
|
||||
goto reorder;
|
||||
}
|
||||
/* password good, set to dial state */
|
||||
k = 1;
|
||||
i = 0; /* re-set buffer pointer */
|
||||
exten[0] = 0;
|
||||
ast_log(LOG_DEBUG,"Successful DISA log-in on chan %s\n",chan->name);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
exten[i++] = j; /* save digit */
|
||||
exten[i] = 0;
|
||||
if (!k) continue; /* if getting password, continue doing it */
|
||||
/* if this exists */
|
||||
if (ast_exists_extension(chan,ourcontext,exten,1, chan->callerid))
|
||||
{
|
||||
strcpy(chan->exten,exten);
|
||||
strcpy(chan->context,ourcontext);
|
||||
chan->priority = 0;
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
/* if can do some more, do it */
|
||||
if (ast_canmatch_extension(chan,ourcontext,exten,1, chan->callerid)) continue;
|
||||
}
|
||||
reorder:
|
||||
/* something is invalid, give em reorder forever */
|
||||
x = 0;
|
||||
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;
|
||||
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.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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, disa_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
@@ -28,17 +28,11 @@ static char *tdesc = "Simple Echo Application";
|
||||
|
||||
static char *app = "Echo";
|
||||
|
||||
static char *synopsis = "Echo audio read back to the user";
|
||||
|
||||
static char *descrip =
|
||||
" Echo(): Echo audio read from channel back to the channel. Returns 0\n"
|
||||
"if the user exits with the '#' key, or -1 if the user hangs up.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int echo_exec(struct ast_channel *chan, void *data)
|
||||
static int skel_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=-1;
|
||||
struct localuser *u;
|
||||
@@ -57,7 +51,6 @@ static int echo_exec(struct ast_channel *chan, void *data)
|
||||
if (ast_write(chan, f))
|
||||
break;
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
@@ -71,7 +64,7 @@ int unload_module(void)
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, echo_exec, synopsis, descrip);
|
||||
return ast_register_application(app, skel_exec);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
@@ -85,8 +78,3 @@ int usecount(void)
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* App to transmit an image
|
||||
*
|
||||
* 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/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/image.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Image Transmission Application";
|
||||
|
||||
static char *app = "SendImage";
|
||||
|
||||
static char *synopsis = "Send an image file";
|
||||
|
||||
static char *descrip =
|
||||
" SendImage(filename): Sends an image on a channel. If the channel\n"
|
||||
"does not support image transport, and there exists a step with\n"
|
||||
"priority n + 101, then execution will continue at that step.\n"
|
||||
"Otherwise, execution will continue at the next priority level.\n"
|
||||
"SendImage only returns 0 if the image was sent correctly or if\n"
|
||||
"the channel does not support image transport, and -1 otherwise.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int sendimage_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
struct localuser *u;
|
||||
if (!data || !strlen((char *)data)) {
|
||||
ast_log(LOG_WARNING, "SendImage requires an argument (filename)\n");
|
||||
return -1;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
if (!ast_supports_images(chan)) {
|
||||
/* Does not support transport */
|
||||
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
|
||||
chan->priority += 100;
|
||||
return 0;
|
||||
}
|
||||
res = ast_send_image(chan, data);
|
||||
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, sendimage_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
@@ -37,12 +37,6 @@ static char *tdesc = "Intercom using /dev/dsp for output";
|
||||
|
||||
static char *app = "Intercom";
|
||||
|
||||
static char *synopsis = "(Obsolete) Send to Intercom";
|
||||
static char *descrip =
|
||||
" Intercom(): Sends the user to the intercom (i.e. /dev/dsp). This program\n"
|
||||
"is generally considered obselete by the chan_oss module. Returns 0 if the\n"
|
||||
"user exits with a DTMF tone, or -1 if they hangup.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
@@ -54,19 +48,19 @@ static int write_audio(short *data, int len)
|
||||
{
|
||||
int res;
|
||||
struct audio_buf_info info;
|
||||
ast_pthread_mutex_lock(&sound_lock);
|
||||
pthread_mutex_lock(&sound_lock);
|
||||
if (sound < 0) {
|
||||
ast_log(LOG_WARNING, "Sound device closed?\n");
|
||||
ast_pthread_mutex_unlock(&sound_lock);
|
||||
pthread_mutex_unlock(&sound_lock);
|
||||
return -1;
|
||||
}
|
||||
if (ioctl(sound, SNDCTL_DSP_GETOSPACE, &info)) {
|
||||
ast_log(LOG_WARNING, "Unable to read output space\n");
|
||||
ast_pthread_mutex_unlock(&sound_lock);
|
||||
pthread_mutex_unlock(&sound_lock);
|
||||
return -1;
|
||||
}
|
||||
res = write(sound, data, len);
|
||||
ast_pthread_mutex_unlock(&sound_lock);
|
||||
pthread_mutex_unlock(&sound_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -122,44 +116,48 @@ static int intercom_exec(struct ast_channel *chan, void *data)
|
||||
int res = 0;
|
||||
struct localuser *u;
|
||||
struct ast_frame *f;
|
||||
int oreadformat;
|
||||
LOCAL_USER_ADD(u);
|
||||
/* Remember original read format */
|
||||
oreadformat = chan->readformat;
|
||||
/* Set mode to signed linear */
|
||||
res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to set format to signed linear on channel %s\n", chan->name);
|
||||
struct ast_channel *trans;
|
||||
if (!data) {
|
||||
ast_log(LOG_WARNING, "Playback requires an argument (filename)\n");
|
||||
return -1;
|
||||
}
|
||||
/* Read packets from the channel */
|
||||
while(!res) {
|
||||
res = ast_waitfor(chan, -1);
|
||||
if (res > 0) {
|
||||
res = 0;
|
||||
f = ast_read(chan);
|
||||
if (f) {
|
||||
if (f->frametype == AST_FRAME_DTMF) {
|
||||
LOCAL_USER_ADD(u);
|
||||
/* See if we need a translator */
|
||||
if (!(chan->format & AST_FORMAT_SLINEAR))
|
||||
trans = ast_translator_create(chan, AST_FORMAT_SLINEAR, AST_DIRECTION_IN);
|
||||
else
|
||||
trans = chan;
|
||||
if (trans) {
|
||||
/* Read packets from the channel */
|
||||
while(!res) {
|
||||
res = ast_waitfor(trans, -1);
|
||||
if (res > 0) {
|
||||
res = 0;
|
||||
f = ast_read(trans);
|
||||
if (f) {
|
||||
if (f->frametype == AST_FRAME_DTMF) {
|
||||
ast_frfree(f);
|
||||
break;
|
||||
} else {
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
if (f->subclass == AST_FORMAT_SLINEAR) {
|
||||
res = write_audio(f->data, f->datalen);
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
} else
|
||||
ast_log(LOG_DEBUG, "Unable to handle non-signed linear frame (%d)\n", f->subclass);
|
||||
}
|
||||
}
|
||||
ast_frfree(f);
|
||||
break;
|
||||
} else {
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
if (f->subclass == AST_FORMAT_SLINEAR) {
|
||||
res = write_audio(f->data, f->datalen);
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
} else
|
||||
ast_log(LOG_DEBUG, "Unable to handle non-signed linear frame (%d)\n", f->subclass);
|
||||
}
|
||||
}
|
||||
ast_frfree(f);
|
||||
} else
|
||||
res = -1;
|
||||
} else
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (trans != chan)
|
||||
ast_translator_destroy(trans);
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Unable to build translator to signed linear format on '%s'\n", chan->name);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
if (!res)
|
||||
ast_set_read_format(chan, oreadformat);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -175,7 +173,7 @@ int load_module(void)
|
||||
{
|
||||
if (create_audio())
|
||||
return -1;
|
||||
return ast_register_application(app, intercom_exec, synopsis, descrip);
|
||||
return ast_register_application(app, intercom_exec);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
@@ -189,8 +187,3 @@ int usecount(void)
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
175
apps/app_mp3.c
175
apps/app_mp3.c
@@ -33,13 +33,6 @@ static char *tdesc = "Silly MP3 Application";
|
||||
|
||||
static char *app = "MP3Player";
|
||||
|
||||
static char *synopsis = "Play an MP3 file or stream";
|
||||
|
||||
static char *descrip =
|
||||
" MP3Player(location) Executes mpg123 to play the given location\n"
|
||||
"which typically would be a filename or a URL. Returns -1 on\n"
|
||||
"hangup or 0 otherwise. User can exit by pressing any key\n.";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
@@ -47,17 +40,12 @@ LOCAL_USER_DECL;
|
||||
static int mp3play(char *filename, int fd)
|
||||
{
|
||||
int res;
|
||||
int x;
|
||||
res = fork();
|
||||
if (res < 0)
|
||||
ast_log(LOG_WARNING, "Fork failed\n");
|
||||
if (res)
|
||||
return res;
|
||||
dup2(fd, STDOUT_FILENO);
|
||||
for (x=0;x<256;x++) {
|
||||
if (x != STDOUT_FILENO)
|
||||
close(x);
|
||||
}
|
||||
/* Execute mpg123, but buffer if it's a net connection */
|
||||
if (strncmp(filename, "http://", 7))
|
||||
execl(MPG_123, MPG_123, "-q", "-s", "-b", "1024", "--mono", "-r", "8000", filename, NULL);
|
||||
@@ -71,17 +59,15 @@ static int mp3_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
struct ast_channel *trans;
|
||||
int fds[2];
|
||||
int rfds[1 + AST_MAX_FDS];
|
||||
int rfds[2];
|
||||
int ms = -1;
|
||||
int pid = -1;
|
||||
int pid;
|
||||
int us;
|
||||
int exception;
|
||||
int owriteformat;
|
||||
struct timeval tv;
|
||||
struct timeval last;
|
||||
struct ast_frame *f;
|
||||
int x;
|
||||
struct myframe {
|
||||
struct ast_frame f;
|
||||
char offset[AST_FRIENDLY_OFFSET];
|
||||
@@ -99,97 +85,87 @@ static int mp3_exec(struct ast_channel *chan, void *data)
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
ast_stopstream(chan);
|
||||
|
||||
owriteformat = chan->writeformat;
|
||||
res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = mp3play((char *)data, fds[1]);
|
||||
if (res >= 0) {
|
||||
pid = res;
|
||||
/* Order is important -- there's almost always going to be mp3... we want to prioritize the
|
||||
user */
|
||||
rfds[AST_MAX_FDS] = fds[0];
|
||||
for (;;) {
|
||||
CHECK_BLOCKING(chan);
|
||||
for (x=0;x<AST_MAX_FDS;x++)
|
||||
rfds[x] = chan->fds[x];
|
||||
res = ast_waitfor_n_fd(rfds, AST_MAX_FDS+1, &ms, &exception);
|
||||
chan->blocking = 0;
|
||||
if (res < 1) {
|
||||
ast_log(LOG_DEBUG, "Hangup detected\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
for(x=0;x<AST_MAX_FDS;x++)
|
||||
if (res == chan->fds[x])
|
||||
break;
|
||||
|
||||
if (x < AST_MAX_FDS) {
|
||||
if (exception)
|
||||
chan->exception = 1;
|
||||
f = ast_read(chan);
|
||||
if (!f) {
|
||||
ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
|
||||
if (chan->format & AST_FORMAT_SLINEAR)
|
||||
trans = chan;
|
||||
else
|
||||
trans = ast_translator_create(chan, AST_FORMAT_SLINEAR, AST_DIRECTION_OUT);
|
||||
if (trans) {
|
||||
res = mp3play((char *)data, fds[1]);
|
||||
if (res >= 0) {
|
||||
pid = res;
|
||||
/* Order is important -- there's almost always going to be mp3... we want to prioritize the
|
||||
user */
|
||||
rfds[0] = trans->fd;
|
||||
rfds[1] = fds[0];
|
||||
for (;;) {
|
||||
CHECK_BLOCKING(trans);
|
||||
res = ast_waitfor_n_fd(rfds, 2, &ms);
|
||||
trans->blocking = 0;
|
||||
if (res < 1) {
|
||||
ast_log(LOG_DEBUG, "Hangup detected\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if (f->frametype == AST_FRAME_DTMF) {
|
||||
ast_log(LOG_DEBUG, "User pressed a key\n");
|
||||
ast_frfree(f);
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
ast_frfree(f);
|
||||
} else if (res == fds[0]) {
|
||||
gettimeofday(&tv, NULL);
|
||||
if (last.tv_sec || last.tv_usec) {
|
||||
/* We should wait at least a frame length */
|
||||
us = sizeof(myf.frdata) / 16 * 1000;
|
||||
/* Subtract 1,000,000 us for each second late we've passed */
|
||||
us -= (tv.tv_sec - last.tv_sec) * 1000000;
|
||||
/* And one for each us late we've passed */
|
||||
us -= (tv.tv_usec - last.tv_usec);
|
||||
/* Sleep that long if needed */
|
||||
if (us > 0)
|
||||
usleep(us);
|
||||
}
|
||||
last = tv;
|
||||
res = read(fds[0], myf.frdata, sizeof(myf.frdata));
|
||||
if (res > 0) {
|
||||
myf.f.frametype = AST_FRAME_VOICE;
|
||||
myf.f.subclass = AST_FORMAT_SLINEAR;
|
||||
myf.f.datalen = res;
|
||||
myf.f.timelen = res / 16;
|
||||
myf.f.mallocd = 0;
|
||||
myf.f.offset = AST_FRIENDLY_OFFSET;
|
||||
myf.f.src = __PRETTY_FUNCTION__;
|
||||
myf.f.data = myf.frdata;
|
||||
if (ast_write(chan, &myf.f) < 0) {
|
||||
} else if (res == trans->fd) {
|
||||
f = ast_read(trans);
|
||||
if (!f) {
|
||||
ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if (f->frametype == AST_FRAME_DTMF) {
|
||||
ast_log(LOG_DEBUG, "User pressed a key\n");
|
||||
ast_frfree(f);
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
ast_frfree(f);
|
||||
} else if (res == fds[0]) {
|
||||
gettimeofday(&tv, NULL);
|
||||
if (last.tv_sec || last.tv_usec) {
|
||||
/* We should wait at least a frame length */
|
||||
us = sizeof(myf.frdata) / 16 * 1000;
|
||||
/* Subtract 1,000,000 us for each second late we've passed */
|
||||
us -= (tv.tv_sec - last.tv_sec) * 1000000;
|
||||
/* And one for each us late we've passed */
|
||||
us -= (tv.tv_usec - last.tv_usec);
|
||||
/* Sleep that long if needed */
|
||||
if (us > 0)
|
||||
usleep(us);
|
||||
}
|
||||
last = tv;
|
||||
res = read(fds[0], myf.frdata, sizeof(myf.frdata));
|
||||
if (res > 0) {
|
||||
myf.f.frametype = AST_FRAME_VOICE;
|
||||
myf.f.subclass = AST_FORMAT_SLINEAR;
|
||||
myf.f.datalen = res;
|
||||
myf.f.timelen = res / 16;
|
||||
myf.f.mallocd = 0;
|
||||
myf.f.offset = AST_FRIENDLY_OFFSET;
|
||||
myf.f.src = __PRETTY_FUNCTION__;
|
||||
myf.f.data = myf.frdata;
|
||||
if (ast_write(trans, &myf.f) < 0) {
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_DEBUG, "No more mp3\n");
|
||||
res = 0;
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_DEBUG, "No more mp3\n");
|
||||
res = 0;
|
||||
ast_log(LOG_DEBUG, "HuhHHH?\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_DEBUG, "HuhHHH?\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
kill(pid, SIGTERM);
|
||||
}
|
||||
}
|
||||
if (trans != chan)
|
||||
ast_translator_destroy(trans);
|
||||
} else
|
||||
ast_log(LOG_WARNING, "No translator channel available\n");
|
||||
close(fds[0]);
|
||||
close(fds[1]);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
if (pid > -1)
|
||||
kill(pid, SIGKILL);
|
||||
if (!res && owriteformat)
|
||||
ast_set_write_format(chan, owriteformat);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -201,7 +177,7 @@ int unload_module(void)
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, mp3_exec, synopsis, descrip);
|
||||
return ast_register_application(app, mp3_exec);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
@@ -215,8 +191,3 @@ int usecount(void)
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
@@ -25,17 +25,6 @@ static char *tdesc = "Trivial Playback Application";
|
||||
|
||||
static char *app = "Playback";
|
||||
|
||||
static char *synopsis = "Play a file";
|
||||
|
||||
static char *descrip =
|
||||
" Playback(filename[|option]): Plays back a given filename (do not put\n"
|
||||
"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";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
@@ -44,35 +33,18 @@ static int playback_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
struct localuser *u;
|
||||
char tmp[256];
|
||||
char *options;
|
||||
int option_skip=0;
|
||||
if (!data || !strlen((char *)data)) {
|
||||
if (!data) {
|
||||
ast_log(LOG_WARNING, "Playback requires an argument (filename)\n");
|
||||
return -1;
|
||||
}
|
||||
strncpy(tmp, (char *)data, sizeof(tmp));
|
||||
strtok(tmp, "|");
|
||||
options = strtok(NULL, "|");
|
||||
if (options && !strcasecmp(options, "skip"))
|
||||
option_skip = 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 */
|
||||
res = ast_answer(chan);
|
||||
}
|
||||
if (chan->state != AST_STATE_UP)
|
||||
res = ast_answer(chan);
|
||||
if (!res) {
|
||||
ast_stopstream(chan);
|
||||
res = ast_streamfile(chan, tmp, chan->language);
|
||||
if (!res)
|
||||
res = ast_streamfile(chan, (char *)data, chan->language);
|
||||
if (!res)
|
||||
res = ast_waitstream(chan, "");
|
||||
else
|
||||
ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", chan->name, (char *)data);
|
||||
ast_stopstream(chan);
|
||||
}
|
||||
LOCAL_USER_REMOVE(u);
|
||||
@@ -87,7 +59,7 @@ int unload_module(void)
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, playback_exec, synopsis, descrip);
|
||||
return ast_register_application(app, playback_exec);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
@@ -101,8 +73,3 @@ int usecount(void)
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
@@ -1,174 +0,0 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Trivial application to record a sound file
|
||||
*
|
||||
* Copyright (C) 2001, Linux Support Services, Inc.
|
||||
*
|
||||
* Matthew Fredrickson <creslin@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#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 = "Trivial Record Application";
|
||||
|
||||
static char *app = "Record";
|
||||
|
||||
static char *synopsis = "Record to a file";
|
||||
|
||||
static char *descrip =
|
||||
" Record(filename:extension): Records from the channel into a given\n"
|
||||
"filename. If the file exists it will be overwritten. The 'extension'\n"
|
||||
"is the extension of the file type to be recorded (wav, gsm, etc).\n"
|
||||
"Returns -1 when the user hangs up.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int record_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
int count = 0;
|
||||
int percentflag = 0;
|
||||
char fil[256];
|
||||
char tmp[256];
|
||||
char ext[10];
|
||||
char * vdata; /* Used so I don't have to typecast every use of *data */
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
||||
struct ast_filestream *s = '\0';
|
||||
struct localuser *u;
|
||||
struct ast_frame *f;
|
||||
|
||||
vdata = data; /* explained above */
|
||||
|
||||
|
||||
/* The next few lines of code parse out the filename and header from the input string */
|
||||
if (!vdata) { /* no data implies no filename or anything is present */
|
||||
ast_log(LOG_WARNING, "Record requires an argument (filename)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (; vdata[i] && (vdata[i] != ':') ; i++ ) {
|
||||
if ((vdata[i] == '%') && (vdata[i+1] == 'd')) {
|
||||
percentflag = 1; /* the wildcard is used */
|
||||
}
|
||||
|
||||
if (i == strlen(vdata) ) {
|
||||
ast_log(LOG_WARNING, "No extension found\n");
|
||||
return -1;
|
||||
}
|
||||
fil[i] = vdata[i];
|
||||
}
|
||||
fil[i++] = '\0';
|
||||
|
||||
for (; j < 10 && i < strlen(data); i++, j++)
|
||||
ext[j] = vdata[i];
|
||||
ext[j] = '\0';
|
||||
/* done parsing */
|
||||
|
||||
|
||||
/* these are to allow the use of the %d in the config file for a wild card of sort to
|
||||
create a new file with the inputed name scheme */
|
||||
if (percentflag) {
|
||||
do {
|
||||
snprintf(tmp, 256, fil, count);
|
||||
count++;
|
||||
} while ( ast_fileexists(tmp, ext, chan->language) != -1 );
|
||||
} else
|
||||
strncpy(tmp, fil, 256);
|
||||
/* end of routine mentioned */
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (chan->state != AST_STATE_UP) {
|
||||
res = ast_answer(chan); /* Shouldn't need this, but checking to see if channel is already answered
|
||||
* Theoretically asterisk should already have answered before running the app */
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
/* 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);
|
||||
/* The end of beep code. Now the recording starts */
|
||||
s = ast_writefile( tmp, ext, NULL, O_CREAT|O_TRUNC|O_WRONLY , 0, 0644);
|
||||
|
||||
if (s) {
|
||||
|
||||
while ((f = ast_read(chan))) {
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
res = ast_writestream(s, f);
|
||||
|
||||
if (res) {
|
||||
ast_log(LOG_WARNING, "Problem writing frame\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((f->frametype == AST_FRAME_DTMF) &&
|
||||
(f->subclass == '#')) {
|
||||
ast_frfree(f);
|
||||
break;
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
if (!f) {
|
||||
ast_log(LOG_DEBUG, "Got hangup\n");
|
||||
res = -1;
|
||||
}
|
||||
ast_closestream(s);
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Could not create file %s\n", fil);
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name);
|
||||
|
||||
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, record_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
@@ -68,8 +68,3 @@ int usecount(void)
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
@@ -28,15 +28,6 @@ static char *tdesc = "Generic System() application";
|
||||
|
||||
static char *app = "System";
|
||||
|
||||
static char *synopsis = "Execute a system command";
|
||||
|
||||
static char *descrip =
|
||||
" System(command): Executes a command by using system(). Returns -1 on\n"
|
||||
"failure to execute the specified command. If the command itself executes\n"
|
||||
"but is in error, and if there exists a priority n + 101, where 'n' is the\n"
|
||||
"priority of the current instance, then the channel will be setup to\n"
|
||||
"continue at that priority level. Otherwise, System returns 0.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
@@ -59,7 +50,7 @@ static int skel_exec(struct ast_channel *chan, void *data)
|
||||
ast_log(LOG_WARNING, "Unable to execute '%s'\n", data);
|
||||
res = -1;
|
||||
} else {
|
||||
if (res && ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
|
||||
if (res && ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101))
|
||||
chan->priority+=100;
|
||||
res = 0;
|
||||
}
|
||||
@@ -75,7 +66,7 @@ int unload_module(void)
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, skel_exec, synopsis, descrip);
|
||||
return ast_register_application(app, skel_exec);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
@@ -89,8 +80,3 @@ int usecount(void)
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
137
apps/app_url.c
137
apps/app_url.c
@@ -1,137 +0,0 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* App to transmit a URL
|
||||
*
|
||||
* 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/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/image.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Send URL Applications";
|
||||
|
||||
static char *app = "SendURL";
|
||||
|
||||
static char *synopsis = "Send a URL";
|
||||
|
||||
static char *descrip =
|
||||
" SendURL(URL[|option]): Requests client go to URL. If the client\n"
|
||||
"does not support html transport, and there exists a step with\n"
|
||||
"priority n + 101, then execution will continue at that step.\n"
|
||||
"Otherwise, execution will continue at the next priority level.\n"
|
||||
"SendURL only returns 0 if the URL was sent correctly or if\n"
|
||||
"the channel does not support HTML transport, and -1 otherwise.\n"
|
||||
"If the option 'wait' is specified, execution will wait for an\n"
|
||||
"acknowledgement that the URL has been loaded before continuing\n"
|
||||
"and will return -1 if the peer is unable to load the URL\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int sendurl_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
struct localuser *u;
|
||||
char tmp[256];
|
||||
char *options;
|
||||
int option_wait=0;
|
||||
struct ast_frame *f;
|
||||
if (!data || !strlen((char *)data)) {
|
||||
ast_log(LOG_WARNING, "SendURL requires an argument (URL)\n");
|
||||
return -1;
|
||||
}
|
||||
strncpy(tmp, (char *)data, sizeof(tmp));
|
||||
strtok(tmp, "|");
|
||||
options = strtok(NULL, "|");
|
||||
if (options && !strcasecmp(options, "wait"))
|
||||
option_wait = 1;
|
||||
LOCAL_USER_ADD(u);
|
||||
if (!ast_channel_supports_html(chan)) {
|
||||
/* Does not support transport */
|
||||
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
|
||||
chan->priority += 100;
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
res = ast_channel_sendurl(chan, tmp);
|
||||
if (res > -1) {
|
||||
if (option_wait) {
|
||||
for(;;) {
|
||||
/* Wait for an event */
|
||||
res = ast_waitfor(chan, -1);
|
||||
if (res < 0)
|
||||
break;
|
||||
f = ast_read(chan);
|
||||
if (!f) {
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if (f->frametype == AST_FRAME_HTML) {
|
||||
switch(f->subclass) {
|
||||
case AST_HTML_LDCOMPLETE:
|
||||
res = 0;
|
||||
ast_frfree(f);
|
||||
goto out;
|
||||
break;
|
||||
case AST_HTML_NOSUPPORT:
|
||||
/* Does not support transport */
|
||||
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
|
||||
chan->priority += 100;
|
||||
res = 0;
|
||||
goto out;
|
||||
break;
|
||||
default:
|
||||
ast_log(LOG_WARNING, "Don't know what to do with HTML subclass %d\n", f->subclass);
|
||||
};
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
out:
|
||||
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, sendurl_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
@@ -37,6 +37,10 @@
|
||||
#define VOICEMAIL_CONFIG "voicemail.conf"
|
||||
#define ASTERISK_USERNAME "asterisk"
|
||||
|
||||
/*
|
||||
#define HOSTNAME_OVERRIDE "linux-support.net"
|
||||
*/
|
||||
|
||||
#define SENDMAIL "/usr/sbin/sendmail -t"
|
||||
|
||||
#define INTRO "vm-intro"
|
||||
@@ -50,22 +54,6 @@
|
||||
|
||||
static char *tdesc = "Comedian Mail (Voicemail System)";
|
||||
|
||||
static char *synopsis_vm =
|
||||
"Leave a voicemail message";
|
||||
|
||||
static char *descrip_vm =
|
||||
" VoiceMail([s]extension): Leaves voicemail for a given extension (must be\n"
|
||||
"configured in voicemail.conf). If the extension is preceeded by an 's' then\n"
|
||||
"instructions for leaving the message will be skipped. Returns -1 on error\n"
|
||||
"or mailbox not found, or if the user hangs up. Otherwise, it returns 0. \n";
|
||||
|
||||
static char *synopsis_vmain =
|
||||
"Enter voicemail system";
|
||||
|
||||
static char *descrip_vmain =
|
||||
" VoiceMailMain(): Enters the main voicemail system for the checking of voicemail. Returns\n"
|
||||
" -1 if the user hangs up or 0 otherwise.\n";
|
||||
|
||||
/* Leave a message */
|
||||
static char *app = "VoiceMail";
|
||||
|
||||
@@ -76,18 +64,19 @@ STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int make_dir(char *dest, int len, char *ext, char *mailbox)
|
||||
static char *get_dir(char *ext, char *mailbox)
|
||||
{
|
||||
return snprintf(dest, len, "%s/%s/%s", VM_SPOOL_DIR, ext, mailbox);
|
||||
char *tmp = malloc(strlen(ext) + strlen(VM_SPOOL_DIR) + 3 + strlen(mailbox));
|
||||
sprintf(tmp, "%s/%s/%s", VM_SPOOL_DIR, ext, mailbox);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static int make_file(char *dest, int len, char *dir, int num)
|
||||
static char *get_fn(char *dir, int num)
|
||||
{
|
||||
return snprintf(dest, len, "%s/msg%04d", dir, num);
|
||||
char *tmp = malloc(strlen(dir) + 10);
|
||||
sprintf(tmp, "%s/msg%04d", dir, num);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
static int announce_message(struct ast_channel *chan, char *dir, int msgcnt)
|
||||
{
|
||||
char *fn;
|
||||
@@ -110,37 +99,34 @@ static int announce_message(struct ast_channel *chan, char *dir, int msgcnt)
|
||||
ast_log(LOG_WARNING, "Unable to announce message\n");
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int sendmail(char *srcemail, char *email, char *name, int msgnum, char *mailbox, char *callerid)
|
||||
static int sendmail(char *email, char *name, int msgnum, char *mailbox)
|
||||
{
|
||||
FILE *p;
|
||||
char date[256];
|
||||
char host[256];
|
||||
char who[256];
|
||||
time_t t;
|
||||
struct tm *tm;
|
||||
p = popen(SENDMAIL, "w");
|
||||
if (p) {
|
||||
if (strchr(srcemail, '@'))
|
||||
strncpy(who, srcemail, sizeof(who));
|
||||
else {
|
||||
gethostname(host, sizeof(host));
|
||||
snprintf(who, sizeof(who), "%s@%s", srcemail, host);
|
||||
}
|
||||
gethostname(host, sizeof(host));
|
||||
time(&t);
|
||||
tm = localtime(&t);
|
||||
strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", tm);
|
||||
fprintf(p, "Date: %s\n", date);
|
||||
fprintf(p, "Message-ID: <Asterisk-%d-%s-%d@%s>\n", msgnum, mailbox, getpid(), host);
|
||||
fprintf(p, "From: Asterisk PBX <%s>\n", who);
|
||||
fprintf(p, "From: Asterisk PBX <%s@%s>\n", ASTERISK_USERNAME,
|
||||
#ifdef HOSTNAME_OVERRIDE
|
||||
HOSTNAME_OVERRIDE
|
||||
#else
|
||||
host
|
||||
#endif
|
||||
);
|
||||
fprintf(p, "To: %s <%s>\n", name, email);
|
||||
fprintf(p, "Subject: [PBX]: New message %d in mailbox %s\n\n", msgnum, mailbox);
|
||||
strftime(date, sizeof(date), "%A, %B %d, %Y at %r", tm);
|
||||
fprintf(p, "Dear %s:\n\n\tJust wanted to let you know you were just left a message (number %d)\n"
|
||||
"in mailbox %s from %s, on %s so you might\n"
|
||||
"want to check it when you get a chance. Thanks!\n\n\t\t\t\t--Asterisk\n", name,
|
||||
msgnum, mailbox, (callerid ? callerid : "an unknown caller"), date);
|
||||
"in mailbox %s, on %s so you might\n"
|
||||
"want to check it when you get a chance. Thanks!\n\n\t\t\t\t--Asterisk\n", name, msgnum, mailbox, date);
|
||||
fprintf(p, ".\n");
|
||||
pclose(p);
|
||||
} else {
|
||||
@@ -150,51 +136,34 @@ static int sendmail(char *srcemail, char *email, char *name, int msgnum, char *m
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_date(char *s, int len)
|
||||
{
|
||||
struct tm *tm;
|
||||
time_t t;
|
||||
t = time(0);
|
||||
tm = localtime(&t);
|
||||
return strftime(s, len, "%a %b %e %r %Z %Y", tm);
|
||||
}
|
||||
|
||||
static int leave_voicemail(struct ast_channel *chan, char *ext, int silent)
|
||||
{
|
||||
struct ast_config *cfg;
|
||||
char *copy, *name, *passwd, *email, *fmt, *fmts;
|
||||
char *copy, *name, *passwd, *email, *dir, *fmt, *fmts, *fn=NULL;
|
||||
char comment[256];
|
||||
struct ast_filestream *writer=NULL, *others[MAX_OTHER_FORMATS];
|
||||
char *sfmt[MAX_OTHER_FORMATS];
|
||||
char txtfile[256];
|
||||
FILE *txt;
|
||||
int res = -1, fmtcnt=0, x;
|
||||
int msgnum;
|
||||
int outmsg=0;
|
||||
struct ast_frame *f;
|
||||
char date[256];
|
||||
char dir[256];
|
||||
char fn[256];
|
||||
char *astemail;
|
||||
|
||||
cfg = ast_load(VOICEMAIL_CONFIG);
|
||||
if (!cfg) {
|
||||
ast_log(LOG_WARNING, "No such configuration file %s\n", VOICEMAIL_CONFIG);
|
||||
return -1;
|
||||
}
|
||||
if (!(astemail = ast_variable_retrieve(cfg, "general", "serveremail")))
|
||||
astemail = ASTERISK_USERNAME;
|
||||
if ((copy = ast_variable_retrieve(cfg, NULL, ext))) {
|
||||
/* Make sure they have an entry in the config */
|
||||
copy = strdup(copy);
|
||||
passwd = strtok(copy, ",");
|
||||
name = strtok(NULL, ",");
|
||||
email = strtok(NULL, ",");
|
||||
make_dir(dir, sizeof(dir), ext, "");
|
||||
dir = get_dir(ext, "");
|
||||
/* It's easier just to try to make it than to check for its existence */
|
||||
if (mkdir(dir, 0700) && (errno != EEXIST))
|
||||
ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dir, strerror(errno));
|
||||
make_dir(dir, sizeof(dir), ext, "INBOX");
|
||||
dir = get_dir(ext, "INBOX");
|
||||
if (mkdir(dir, 0700) && (errno != EEXIST))
|
||||
ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dir, strerror(errno));
|
||||
/* Stream an info message */
|
||||
@@ -207,7 +176,9 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent)
|
||||
fmt = strtok(fmts, "|");
|
||||
msgnum = 0;
|
||||
do {
|
||||
make_file(fn, sizeof(fn), dir, msgnum);
|
||||
if (fn)
|
||||
free(fn);
|
||||
fn = get_fn(dir, msgnum);
|
||||
snprintf(comment, sizeof(comment), "Voicemail from %s to %s (%s) on %s\n",
|
||||
(chan->callerid ? chan->callerid : "Unknown"),
|
||||
name, ext, chan->name);
|
||||
@@ -221,33 +192,6 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent)
|
||||
msgnum++;
|
||||
} while(!writer && (msgnum < MAXMSG));
|
||||
if (writer) {
|
||||
/* Store information */
|
||||
snprintf(txtfile, sizeof(txtfile), "%s.txt", fn);
|
||||
txt = fopen(txtfile, "w+");
|
||||
if (txt) {
|
||||
get_date(date, sizeof(date));
|
||||
fprintf(txt,
|
||||
"#\n"
|
||||
"# Message Information file\n"
|
||||
"#\n"
|
||||
"origmailbox=%s\n"
|
||||
"context=%s\n"
|
||||
"exten=%s\n"
|
||||
"priority=%d\n"
|
||||
"callerchan=%s\n"
|
||||
"callerid=%s\n"
|
||||
"origdate=%s\n",
|
||||
ext,
|
||||
chan->context,
|
||||
chan->exten,
|
||||
chan->priority,
|
||||
chan->name,
|
||||
chan->callerid ? chan->callerid : "Unknown",
|
||||
date);
|
||||
fclose(txt);
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Error opening text file for output\n");
|
||||
|
||||
/* We need to reset these values */
|
||||
free(fmts);
|
||||
fmt = ast_variable_retrieve(cfg, "general", "format");
|
||||
@@ -329,7 +273,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent)
|
||||
}
|
||||
/* Send e-mail if applicable */
|
||||
if (email)
|
||||
sendmail(astemail, email, name, msgnum, ext, chan->callerid);
|
||||
sendmail(email, name, msgnum, ext);
|
||||
}
|
||||
} else {
|
||||
if (msgnum < MAXMSG)
|
||||
@@ -337,6 +281,8 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent)
|
||||
else
|
||||
ast_log(LOG_WARNING, "Too many messages in mailbox %s\n", ext);
|
||||
}
|
||||
if (fn)
|
||||
free(fn);
|
||||
free(fmts);
|
||||
} else
|
||||
ast_log(LOG_WARNING, "No format to save messages in \n");
|
||||
@@ -344,6 +290,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent)
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Unable to playback instructions\n");
|
||||
|
||||
free(dir);
|
||||
free(copy);
|
||||
} else
|
||||
ast_log(LOG_WARNING, "No entry in voicemail config file for '%s'\n", ext);
|
||||
@@ -352,276 +299,23 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent)
|
||||
return res;
|
||||
}
|
||||
|
||||
static char *mbox(int id)
|
||||
{
|
||||
switch(id) {
|
||||
case 0:
|
||||
return "INBOX";
|
||||
case 1:
|
||||
return "Old";
|
||||
case 2:
|
||||
return "Work";
|
||||
case 3:
|
||||
return "Family";
|
||||
case 4:
|
||||
return "Friends";
|
||||
case 5:
|
||||
return "Cust1";
|
||||
case 6:
|
||||
return "Cust2";
|
||||
case 7:
|
||||
return "Cust3";
|
||||
case 8:
|
||||
return "Cust4";
|
||||
case 9:
|
||||
return "Cust5";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static int count_messages(char *dir)
|
||||
{
|
||||
int x;
|
||||
char fn[256];
|
||||
for (x=0;x<MAXMSG;x++) {
|
||||
make_file(fn, sizeof(fn), dir, x);
|
||||
if (ast_fileexists(fn, NULL, NULL) < 1)
|
||||
break;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
static int play_and_wait(struct ast_channel *chan, char *fn)
|
||||
{
|
||||
int d;
|
||||
d = ast_streamfile(chan, fn, chan->language);
|
||||
if (d)
|
||||
return d;
|
||||
d = ast_waitstream(chan, AST_DIGIT_ANY);
|
||||
return d;
|
||||
}
|
||||
|
||||
static int say_and_wait(struct ast_channel *chan, int num)
|
||||
{
|
||||
int d;
|
||||
d = ast_say_number(chan, num, chan->language);
|
||||
return d;
|
||||
}
|
||||
|
||||
static int copy(char *infile, char *outfile)
|
||||
{
|
||||
int ifd;
|
||||
int ofd;
|
||||
int res;
|
||||
int len;
|
||||
char buf[4096];
|
||||
if ((ifd = open(infile, O_RDONLY)) < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to open %s in read-only mode\n", infile);
|
||||
return -1;
|
||||
}
|
||||
if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, 0600)) < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to open %s in write-only mode\n", outfile);
|
||||
close(ifd);
|
||||
return -1;
|
||||
}
|
||||
do {
|
||||
len = read(ifd, buf, sizeof(buf));
|
||||
if (len < 0) {
|
||||
ast_log(LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno));
|
||||
close(ifd);
|
||||
close(ofd);
|
||||
unlink(outfile);
|
||||
}
|
||||
if (len) {
|
||||
res = write(ofd, buf, len);
|
||||
if (res != len) {
|
||||
ast_log(LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, res, len, strerror(errno));
|
||||
close(ifd);
|
||||
close(ofd);
|
||||
unlink(outfile);
|
||||
}
|
||||
}
|
||||
} while(len);
|
||||
close(ifd);
|
||||
close(ofd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int save_to_folder(char *dir, int msg, char *username, int box)
|
||||
{
|
||||
char sfn[256];
|
||||
char dfn[256];
|
||||
char ddir[256];
|
||||
char txt[256];
|
||||
char ntxt[256];
|
||||
char *dbox = mbox(box);
|
||||
int x;
|
||||
make_file(sfn, sizeof(sfn), dir, msg);
|
||||
make_dir(ddir, sizeof(ddir), username, dbox);
|
||||
mkdir(ddir, 0700);
|
||||
for (x=0;x<MAXMSG;x++) {
|
||||
make_file(dfn, sizeof(dfn), ddir, x);
|
||||
if (ast_fileexists(dfn, NULL, NULL) < 0)
|
||||
break;
|
||||
}
|
||||
if (x >= MAXMSG)
|
||||
return -1;
|
||||
ast_filecopy(sfn, dfn, NULL);
|
||||
if (strcmp(sfn, dfn)) {
|
||||
snprintf(txt, sizeof(txt), "%s.txt", sfn);
|
||||
snprintf(ntxt, sizeof(ntxt), "%s.txt", dfn);
|
||||
copy(txt, ntxt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_folder(struct ast_channel *chan, int start)
|
||||
{
|
||||
int x;
|
||||
int d;
|
||||
char fn[256];
|
||||
d = play_and_wait(chan, "vm-press");
|
||||
if (d)
|
||||
return d;
|
||||
for (x = start; x< 5; x++) {
|
||||
if ((d = ast_say_number(chan, x, chan->language)))
|
||||
return d;
|
||||
d = play_and_wait(chan, "vm-for");
|
||||
if (d)
|
||||
return d;
|
||||
snprintf(fn, sizeof(fn), "vm-%s", mbox(x));
|
||||
d = play_and_wait(chan, fn);
|
||||
if (d)
|
||||
return d;
|
||||
d = play_and_wait(chan, "vm-messages");
|
||||
if (d)
|
||||
return d;
|
||||
d = ast_waitfordigit(chan, 500);
|
||||
if (d)
|
||||
return d;
|
||||
}
|
||||
d = play_and_wait(chan, "vm-tocancel");
|
||||
if (d)
|
||||
return d;
|
||||
d = ast_waitfordigit(chan, 4000);
|
||||
return d;
|
||||
}
|
||||
|
||||
#define WAITCMD(a) do { \
|
||||
d = (a); \
|
||||
if (d < 0) \
|
||||
goto out; \
|
||||
if (d) \
|
||||
goto cmd; \
|
||||
} while(0)
|
||||
|
||||
#define WAITFILE2(file) do { \
|
||||
if (ast_streamfile(chan, file, chan->language)) \
|
||||
ast_log(LOG_WARNING, "Unable to play message %s\n", file); \
|
||||
d = ast_waitstream(chan, AST_DIGIT_ANY); \
|
||||
if (d < 0) { \
|
||||
goto out; \
|
||||
}\
|
||||
} while(0)
|
||||
|
||||
#define WAITFILE(file) do { \
|
||||
if (ast_streamfile(chan, file, chan->language)) \
|
||||
ast_log(LOG_WARNING, "Unable to play message %s\n", file); \
|
||||
d = ast_waitstream(chan, AST_DIGIT_ANY); \
|
||||
if (!d) { \
|
||||
repeats = 0; \
|
||||
goto instructions; \
|
||||
} else if (d < 0) { \
|
||||
goto out; \
|
||||
} else goto cmd;\
|
||||
} while(0)
|
||||
|
||||
#define PLAYMSG(a) do { \
|
||||
starting = 0; \
|
||||
if (!a) \
|
||||
WAITFILE2("vm-first"); \
|
||||
else if (a == lastmsg) \
|
||||
WAITFILE2("vm-last"); \
|
||||
WAITFILE2("vm-message"); \
|
||||
if (a && (a != lastmsg)) { \
|
||||
d = ast_say_number(chan, a + 1, chan->language); \
|
||||
if (d < 0) goto out; \
|
||||
if (d) goto cmd; \
|
||||
} \
|
||||
make_file(fn, sizeof(fn), curdir, a); \
|
||||
heard[a] = 1; \
|
||||
WAITFILE(fn); \
|
||||
} while(0)
|
||||
|
||||
#define CLOSE_MAILBOX do { \
|
||||
if (lastmsg > -1) { \
|
||||
/* Get the deleted messages fixed */ \
|
||||
curmsg = -1; \
|
||||
for (x=0;x<=lastmsg;x++) { \
|
||||
if (!deleted[x] && (strcasecmp(curbox, "INBOX") || !heard[x])) { \
|
||||
/* Save this message. It's not in INBOX or hasn't been heard */ \
|
||||
curmsg++; \
|
||||
make_file(fn, sizeof(fn), curdir, x); \
|
||||
make_file(fn2, sizeof(fn2), curdir, curmsg); \
|
||||
if (strcmp(fn, fn2)) { \
|
||||
snprintf(txt, sizeof(txt), "%s.txt", fn); \
|
||||
snprintf(ntxt, sizeof(ntxt), "%s.txt", fn2); \
|
||||
ast_filerename(fn, fn2, NULL); \
|
||||
rename(txt, ntxt); \
|
||||
} \
|
||||
} else if (!strcasecmp(curbox, "INBOX") && heard[x] && !deleted[x]) { \
|
||||
/* Move to old folder before deleting */ \
|
||||
save_to_folder(curdir, x, username, 1); \
|
||||
} \
|
||||
} \
|
||||
for (x = curmsg + 1; x<=lastmsg; x++) { \
|
||||
make_file(fn, sizeof(fn), curdir, x); \
|
||||
snprintf(txt, sizeof(txt), "%s.txt", fn); \
|
||||
ast_filedelete(fn, NULL); \
|
||||
unlink(txt); \
|
||||
} \
|
||||
} \
|
||||
memset(deleted, 0, sizeof(deleted)); \
|
||||
memset(heard, 0, sizeof(heard)); \
|
||||
} while(0)
|
||||
|
||||
#define OPEN_MAILBOX(a) do { \
|
||||
strcpy(curbox, mbox(a)); \
|
||||
make_dir(curdir, sizeof(curdir), username, curbox); \
|
||||
lastmsg = count_messages(curdir) - 1; \
|
||||
snprintf(vmbox, sizeof(vmbox), "vm-%s", curbox); \
|
||||
} while (0)
|
||||
|
||||
static int vm_execmain(struct ast_channel *chan, void *data)
|
||||
{
|
||||
/* XXX This is, admittedly, some pretty horrendus code. For some
|
||||
reason it just seemed a lot easier to do with GOTO's. I feel
|
||||
like I'm back in my GWBASIC days. XXX */
|
||||
/* XXX This is, admittedly, some pretty horrendus code XXX */
|
||||
int res=-1;
|
||||
int valid = 0;
|
||||
int curmsg = 0;
|
||||
int maxmsg = 0;
|
||||
int x;
|
||||
char *fn, *nfn;
|
||||
char d;
|
||||
struct localuser *u;
|
||||
char username[80];
|
||||
char password[80], *copy;
|
||||
char curbox[80];
|
||||
char curdir[256];
|
||||
char vmbox[256];
|
||||
char fn[256];
|
||||
char fn2[256];
|
||||
int x;
|
||||
char ntxt[256];
|
||||
char txt[256];
|
||||
int deleted[MAXMSG] = { 0, };
|
||||
int heard[MAXMSG] = { 0, };
|
||||
int newmessages;
|
||||
int oldmessages;
|
||||
int repeats = 0;
|
||||
int curmsg = 0;
|
||||
int lastmsg = 0;
|
||||
int starting = 1;
|
||||
int box;
|
||||
int deleted[MAXMSG];
|
||||
struct ast_config *cfg;
|
||||
int state;
|
||||
char *dir=NULL;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
cfg = ast_load(VOICEMAIL_CONFIG);
|
||||
@@ -629,18 +323,13 @@ static int vm_execmain(struct ast_channel *chan, void *data)
|
||||
ast_log(LOG_WARNING, "No voicemail configuration\n");
|
||||
goto out;
|
||||
}
|
||||
if (chan->state != AST_STATE_UP)
|
||||
ast_answer(chan);
|
||||
if (ast_streamfile(chan, "vm-login", chan->language)) {
|
||||
ast_log(LOG_WARNING, "Couldn't stream login file\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Authenticate them and get their mailbox/password */
|
||||
|
||||
do {
|
||||
/* Prompt for, and read in the username */
|
||||
if (ast_readstring(chan, username, sizeof(username), 2000, 10000, "#") < 0) {
|
||||
if (ast_readstring(chan, username, sizeof(username), 2000, 5000, "#")) {
|
||||
ast_log(LOG_WARNING, "Couldn't read username\n");
|
||||
goto out;
|
||||
}
|
||||
@@ -654,7 +343,7 @@ static int vm_execmain(struct ast_channel *chan, void *data)
|
||||
ast_log(LOG_WARNING, "Unable to stream password file\n");
|
||||
goto out;
|
||||
}
|
||||
if (ast_readstring(chan, password, sizeof(password), 2000, 10000, "#") < 0) {
|
||||
if (ast_readstring(chan, password, sizeof(password), 2000, 5000, "#")) {
|
||||
ast_log(LOG_WARNING, "Unable to read password\n");
|
||||
goto out;
|
||||
}
|
||||
@@ -676,175 +365,202 @@ static int vm_execmain(struct ast_channel *chan, void *data)
|
||||
break;
|
||||
}
|
||||
} while (!valid);
|
||||
|
||||
if (valid) {
|
||||
OPEN_MAILBOX(1);
|
||||
oldmessages = lastmsg + 1;
|
||||
/* Start in INBOX */
|
||||
OPEN_MAILBOX(0);
|
||||
newmessages = lastmsg + 1;
|
||||
|
||||
WAITCMD(play_and_wait(chan, "vm-youhave"));
|
||||
if (newmessages) {
|
||||
WAITCMD(say_and_wait(chan, newmessages));
|
||||
WAITCMD(play_and_wait(chan, "vm-INBOX"));
|
||||
if (newmessages == 1)
|
||||
WAITCMD(play_and_wait(chan, "vm-message"));
|
||||
else
|
||||
WAITCMD(play_and_wait(chan, "vm-messages"));
|
||||
|
||||
if (oldmessages)
|
||||
WAITCMD(play_and_wait(chan, "vm-and"));
|
||||
}
|
||||
if (oldmessages) {
|
||||
WAITCMD(say_and_wait(chan, oldmessages));
|
||||
WAITCMD(play_and_wait(chan, "vm-Old"));
|
||||
if (oldmessages == 1)
|
||||
WAITCMD(play_and_wait(chan, "vm-message"));
|
||||
else
|
||||
WAITCMD(play_and_wait(chan, "vm-messages"));
|
||||
}
|
||||
if (!oldmessages && !newmessages) {
|
||||
WAITCMD(play_and_wait(chan, "vm-no"));
|
||||
WAITCMD(play_and_wait(chan, "vm-messages"));
|
||||
}
|
||||
if (!newmessages && oldmessages) {
|
||||
/* If we only have old messages start here */
|
||||
OPEN_MAILBOX(1);
|
||||
}
|
||||
repeats = 0;
|
||||
starting = 1;
|
||||
instructions:
|
||||
if (starting) {
|
||||
if (lastmsg > -1) {
|
||||
WAITCMD(play_and_wait(chan, "vm-onefor"));
|
||||
WAITCMD(play_and_wait(chan, vmbox));
|
||||
WAITCMD(play_and_wait(chan, "vm-messages"));
|
||||
}
|
||||
WAITCMD(play_and_wait(chan, "vm-opts"));
|
||||
} else {
|
||||
if (curmsg)
|
||||
WAITCMD(play_and_wait(chan, "vm-prev"));
|
||||
WAITCMD(play_and_wait(chan, "vm-repeat"));
|
||||
if (curmsg != lastmsg)
|
||||
WAITCMD(play_and_wait(chan, "vm-next"));
|
||||
if (!deleted[curmsg])
|
||||
WAITCMD(play_and_wait(chan, "vm-delete"));
|
||||
else
|
||||
WAITCMD(play_and_wait(chan, "vm-undelete"));
|
||||
WAITCMD(play_and_wait(chan, "vm-toforward"));
|
||||
WAITCMD(play_and_wait(chan, "vm-savemessage"));
|
||||
}
|
||||
WAITCMD(play_and_wait(chan, "vm-helpexit"));
|
||||
d = ast_waitfordigit(chan, 6000);
|
||||
if (d < 0)
|
||||
dir = get_dir(username, "INBOX");
|
||||
if (!dir)
|
||||
goto out;
|
||||
|
||||
deleted[0] = 0;
|
||||
/* Find out how many messages are there, mark all as
|
||||
not deleted. */
|
||||
do {
|
||||
fn = get_fn(dir, maxmsg);
|
||||
if ((res = ast_fileexists(fn, NULL, chan->language))>0) {
|
||||
maxmsg++;
|
||||
deleted[maxmsg] = 0;
|
||||
}
|
||||
free(fn);
|
||||
} while(res > 0);
|
||||
if (ast_streamfile(chan, "vm-youhave", chan->language))
|
||||
goto out;
|
||||
if ((d=ast_waitstream(chan, AST_DIGIT_ANY)) < 0)
|
||||
goto out;
|
||||
ast_stopstream(chan);
|
||||
if (!d) {
|
||||
repeats++;
|
||||
if (repeats > 2) {
|
||||
play_and_wait(chan, "vm-goodbye");
|
||||
goto out;
|
||||
/* If they haven't interrupted us, play the message count */
|
||||
if (maxmsg > 0) {
|
||||
if ((d = ast_say_number(chan, maxmsg, chan->language)) < 0)
|
||||
goto out;
|
||||
} else {
|
||||
if (ast_streamfile(chan, "vm-no", chan->language))
|
||||
goto out;
|
||||
if ((d=ast_waitstream(chan, AST_DIGIT_ANY)) < 0)
|
||||
goto out;
|
||||
ast_stopstream(chan);
|
||||
}
|
||||
if (!d) {
|
||||
/* And if they still haven't, give them the last word */
|
||||
if (ast_streamfile(chan, ((maxmsg == 1) ? "vm-message" : "vm-messages"), chan->language))
|
||||
goto out;
|
||||
if (ast_waitstream(chan, AST_DIGIT_ANY) < 0)
|
||||
goto out;
|
||||
ast_stopstream(chan);
|
||||
}
|
||||
goto instructions;
|
||||
}
|
||||
cmd:
|
||||
switch(d) {
|
||||
case '2':
|
||||
box = play_and_wait(chan, "vm-changeto");
|
||||
if (box < 0)
|
||||
goto out;
|
||||
while((box < '0') || (box > '9')) {
|
||||
box = get_folder(chan, 0);
|
||||
if (box < 0)
|
||||
res = -1;
|
||||
|
||||
#define STATE_STARTING 1
|
||||
#define STATE_MESSAGE 2
|
||||
#define STATE_MESSAGE_PLAYING 3
|
||||
state = STATE_STARTING;
|
||||
ast_log(LOG_EVENT, "User '%s' logged in on channel '%s' with %d message(s).\n", username, chan->name, maxmsg);
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "User '%s' logged in on channel %s with %d messages\n", username, chan->name, maxmsg);
|
||||
if (!ast_streamfile(chan, "vm-instructions", chan->language)) {
|
||||
for(;;) {
|
||||
if (chan->stream || (chan->trans && chan->trans->stream)) {
|
||||
d = ast_waitstream(chan, AST_DIGIT_ANY);
|
||||
ast_stopstream(chan);
|
||||
if (!d && (state == STATE_MESSAGE_PLAYING)) {
|
||||
state = STATE_MESSAGE;
|
||||
/* If it runs out playing a message, then give directions */
|
||||
if (!(d = ast_streamfile(chan, "vm-msginstruct", chan->language)))
|
||||
d = ast_waitstream(chan, AST_DIGIT_ANY);
|
||||
ast_stopstream(chan);
|
||||
}
|
||||
if (!d)
|
||||
d = ast_waitfordigit(chan, COMMAND_TIMEOUT);
|
||||
} else
|
||||
d = ast_waitfordigit(chan, COMMAND_TIMEOUT);
|
||||
if (d < 0)
|
||||
goto out;
|
||||
if (box == '#')
|
||||
goto instructions;
|
||||
}
|
||||
box = box - '0';
|
||||
CLOSE_MAILBOX;
|
||||
OPEN_MAILBOX(box);
|
||||
WAITCMD(play_and_wait(chan, vmbox));
|
||||
WAITCMD(play_and_wait(chan, "vm-messages"));
|
||||
starting = 1;
|
||||
goto instructions;
|
||||
case '4':
|
||||
if (curmsg) {
|
||||
curmsg--;
|
||||
PLAYMSG(curmsg);
|
||||
} else {
|
||||
WAITCMD(play_and_wait(chan, "vm-nomore"));
|
||||
goto instructions;
|
||||
restart:
|
||||
if (!d || (d == '*')) {
|
||||
/* If they don't say anything, play back a message. We'll decide which one is
|
||||
best based up on where they are. Ditto if they press the '*' key. */
|
||||
switch(state) {
|
||||
case STATE_STARTING:
|
||||
if (ast_streamfile(chan, "vm-instructions", chan->language))
|
||||
goto out;
|
||||
break;
|
||||
case STATE_MESSAGE:
|
||||
case STATE_MESSAGE_PLAYING:
|
||||
if (ast_streamfile(chan, "vm-msginstruct", chan->language))
|
||||
goto out;
|
||||
break;
|
||||
default:
|
||||
ast_log(LOG_WARNING, "What do I do when they timeout/* in state %d?\n", state);
|
||||
}
|
||||
} else {
|
||||
/* XXX Should we be command-compatible with Meridian mail? Their system seems
|
||||
very confusing, but also widely used XXX */
|
||||
/* They've entered (or started to enter) a command */
|
||||
switch(d) {
|
||||
case '0':
|
||||
if (curmsg < maxmsg) {
|
||||
deleted[curmsg] = !deleted[curmsg];
|
||||
if (deleted[curmsg]) {
|
||||
if (ast_streamfile(chan, "vm-deleted", chan->language))
|
||||
goto out;
|
||||
} else {
|
||||
if (ast_streamfile(chan, "vm-undeleted", chan->language))
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
if (ast_streamfile(chan, "vm-nomore", chan->language))
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
case '1':
|
||||
curmsg = 0;
|
||||
if (maxmsg > 0) {
|
||||
/* Yuck */
|
||||
if ((d = announce_message(chan, dir, curmsg)) > 0)
|
||||
goto restart;
|
||||
else if (d < 0)
|
||||
goto out;
|
||||
} else {
|
||||
if (ast_streamfile(chan, "vm-nomore", chan->language))
|
||||
goto out;
|
||||
}
|
||||
state = STATE_MESSAGE_PLAYING;
|
||||
break;
|
||||
case '4':
|
||||
if (curmsg > 0)
|
||||
curmsg--;
|
||||
/* Yuck */
|
||||
if ((d = announce_message(chan, dir, curmsg)) > 0)
|
||||
goto restart;
|
||||
else if (d < 0)
|
||||
goto out;
|
||||
state = STATE_MESSAGE_PLAYING;
|
||||
break;
|
||||
case '5':
|
||||
if ((d = announce_message(chan, dir, curmsg)) > 0)
|
||||
goto restart;
|
||||
else if (d < 0)
|
||||
goto out;
|
||||
state = STATE_MESSAGE_PLAYING;
|
||||
break;
|
||||
case '6':
|
||||
if (curmsg < maxmsg - 1) {
|
||||
curmsg++;
|
||||
if ((d = announce_message(chan, dir, curmsg)) > 0)
|
||||
goto restart;
|
||||
else if (d < 0)
|
||||
goto out;
|
||||
} else {
|
||||
if (ast_streamfile(chan, "vm-nomore", chan->language))
|
||||
goto out;
|
||||
}
|
||||
state = STATE_MESSAGE_PLAYING;
|
||||
break;
|
||||
/* XXX Message compose? It's easy! Just read their # and, assuming it's in the config,
|
||||
call the routine as if it were called from the PBX proper XXX */
|
||||
case '#':
|
||||
if (ast_streamfile(chan, "vm-goodbye", chan->language))
|
||||
goto out;
|
||||
if (ast_waitstream(chan, ""))
|
||||
goto out;
|
||||
res = 0;
|
||||
goto out;
|
||||
break;
|
||||
default:
|
||||
/* Double yuck */
|
||||
d = '*';
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
}
|
||||
case '1':
|
||||
curmsg = 0;
|
||||
/* Fall through */
|
||||
case '5':
|
||||
if (lastmsg > -1) {
|
||||
PLAYMSG(curmsg);
|
||||
} else {
|
||||
WAITCMD(play_and_wait(chan, "vm-youhave"));
|
||||
WAITCMD(play_and_wait(chan, "vm-no"));
|
||||
snprintf(fn, sizeof(fn), "vm-%s", curbox);
|
||||
WAITCMD(play_and_wait(chan, fn));
|
||||
WAITCMD(play_and_wait(chan, "vm-messages"));
|
||||
goto instructions;
|
||||
}
|
||||
case '6':
|
||||
if (curmsg < lastmsg) {
|
||||
curmsg++;
|
||||
PLAYMSG(curmsg);
|
||||
} else {
|
||||
WAITCMD(play_and_wait(chan, "vm-nomore"));
|
||||
goto instructions;
|
||||
}
|
||||
case '7':
|
||||
deleted[curmsg] = !deleted[curmsg];
|
||||
if (deleted[curmsg])
|
||||
WAITCMD(play_and_wait(chan, "vm-deleted"));
|
||||
else
|
||||
WAITCMD(play_and_wait(chan, "vm-undeleted"));
|
||||
goto instructions;
|
||||
case '9':
|
||||
box = play_and_wait(chan, "vm-savefolder");
|
||||
if (box < 0)
|
||||
goto out;
|
||||
while((box < '1') || (box > '9')) {
|
||||
box = get_folder(chan, 1);
|
||||
if (box < 0)
|
||||
goto out;
|
||||
if (box == '#')
|
||||
goto instructions;
|
||||
}
|
||||
box = box - '0';
|
||||
ast_log(LOG_DEBUG, "Save to folder: %s (%d)\n", mbox(box), box);
|
||||
if (save_to_folder(curdir, curmsg, username, box))
|
||||
goto out;
|
||||
deleted[curmsg]=1;
|
||||
WAITCMD(play_and_wait(chan, "vm-message"));
|
||||
WAITCMD(say_and_wait(chan, curmsg + 1) );
|
||||
WAITCMD(play_and_wait(chan, "vm-savedto"));
|
||||
snprintf(fn, sizeof(fn), "vm-%s", mbox(box));
|
||||
WAITCMD(play_and_wait(chan, fn));
|
||||
WAITCMD(play_and_wait(chan, "vm-messages"));
|
||||
goto instructions;
|
||||
case '*':
|
||||
if (!starting) {
|
||||
WAITCMD(play_and_wait(chan, "vm-onefor"));
|
||||
WAITCMD(play_and_wait(chan, vmbox));
|
||||
WAITCMD(play_and_wait(chan, "vm-messages"));
|
||||
WAITCMD(play_and_wait(chan, "vm-opts"));
|
||||
}
|
||||
goto instructions;
|
||||
case '#':
|
||||
play_and_wait(chan, "vm-goodbye");
|
||||
goto out;
|
||||
default:
|
||||
goto instructions;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
CLOSE_MAILBOX;
|
||||
ast_stopstream(chan);
|
||||
if (maxmsg) {
|
||||
/* Get the deleted messages fixed */
|
||||
curmsg = -1;
|
||||
for (x=0;x<maxmsg;x++) {
|
||||
if (!deleted[x]) {
|
||||
curmsg++;
|
||||
fn = get_fn(dir, x);
|
||||
nfn = get_fn(dir, curmsg);
|
||||
if (strcmp(fn, nfn))
|
||||
ast_filerename(fn, nfn, NULL);
|
||||
free(fn);
|
||||
free(nfn);
|
||||
}
|
||||
}
|
||||
for (x = curmsg + 1; x<maxmsg; x++) {
|
||||
fn = get_fn(dir, x);
|
||||
if (fn) {
|
||||
ast_filedelete(fn, NULL);
|
||||
free(fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dir)
|
||||
free(dir);
|
||||
if (cfg)
|
||||
ast_destroy(cfg);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
@@ -866,8 +582,6 @@ static int vm_exec(struct ast_channel *chan, void *data)
|
||||
silent++;
|
||||
ext++;
|
||||
}
|
||||
if (chan->state != AST_STATE_UP)
|
||||
ast_answer(chan);
|
||||
res = leave_voicemail(chan, ext, silent);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
@@ -885,9 +599,9 @@ int unload_module(void)
|
||||
int load_module(void)
|
||||
{
|
||||
int res;
|
||||
res = ast_register_application(app, vm_exec, synopsis_vm, descrip_vm);
|
||||
res = ast_register_application(app, vm_exec);
|
||||
if (!res)
|
||||
res = ast_register_application(app2, vm_execmain, synopsis_vmain, descrip_vmain);
|
||||
res = ast_register_application(app2, vm_execmain);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -902,8 +616,3 @@ int usecount(void)
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
@@ -1,161 +0,0 @@
|
||||
# Here's the doxygen configuration file for the asterisk source
|
||||
# code
|
||||
|
||||
|
||||
|
||||
# Doxygen configuration generated by Doxywizard version 0.1
|
||||
#---------------------------------------------------------------------------
|
||||
# General configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
PROJECT_NAME = Asterisk
|
||||
PROJECT_NUMBER = 0.1.8
|
||||
OUTPUT_DIRECTORY = doc/
|
||||
OUTPUT_LANGUAGE = English
|
||||
EXTRACT_ALL = YES
|
||||
EXTRACT_PRIVATE = NO
|
||||
EXTRACT_STATIC = NO
|
||||
HIDE_UNDOC_MEMBERS = YES
|
||||
HIDE_UNDOC_CLASSES = NO
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
REPEAT_BRIEF = YES
|
||||
ALWAYS_DETAILED_SEC = NO
|
||||
FULL_PATH_NAMES = NO
|
||||
STRIP_FROM_PATH =
|
||||
INTERNAL_DOCS = NO
|
||||
CLASS_DIAGRAMS = YES
|
||||
SOURCE_BROWSER = YES
|
||||
INLINE_SOURCES = NO
|
||||
STRIP_CODE_COMMENTS = NO
|
||||
CASE_SENSE_NAMES = YES
|
||||
HIDE_SCOPE_NAMES = NO
|
||||
VERBATIM_HEADERS = YES
|
||||
SHOW_INCLUDE_FILES = YES
|
||||
JAVADOC_AUTOBRIEF = NO
|
||||
INHERIT_DOCS = YES
|
||||
INLINE_INFO = YES
|
||||
SORT_MEMBER_DOCS = YES
|
||||
DISTRIBUTE_GROUP_DOC = YES
|
||||
TAB_SIZE = 4
|
||||
ENABLED_SECTIONS =
|
||||
GENERATE_TODOLIST = YES
|
||||
GENERATE_TESTLIST = YES
|
||||
GENERATE_BUGLIST = NO
|
||||
ALIASES =
|
||||
MAX_INITIALIZER_LINES = 30
|
||||
OPTIMIZE_OUTPUT_FOR_C = NO
|
||||
SHOW_USED_FILES = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to warning and progress messages
|
||||
#---------------------------------------------------------------------------
|
||||
QUIET = NO
|
||||
WARNINGS = YES
|
||||
WARN_IF_UNDOCUMENTED = YES
|
||||
WARN_FORMAT = "$file:$line: $text"
|
||||
WARN_LOGFILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
INPUT = .
|
||||
FILE_PATTERNS = *.h \
|
||||
*.c
|
||||
RECURSIVE = YES
|
||||
EXCLUDE =
|
||||
EXCLUDE_PATTERNS =
|
||||
EXAMPLE_PATH =
|
||||
EXAMPLE_PATTERNS =
|
||||
IMAGE_PATH =
|
||||
INPUT_FILTER =
|
||||
FILTER_SOURCE_FILES = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
ALPHABETICAL_INDEX = NO
|
||||
COLS_IN_ALPHA_INDEX = 5
|
||||
IGNORE_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the HTML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_HTML = YES
|
||||
HTML_OUTPUT = html
|
||||
HTML_HEADER =
|
||||
HTML_FOOTER =
|
||||
HTML_STYLESHEET =
|
||||
HTML_ALIGN_MEMBERS = YES
|
||||
GENERATE_HTMLHELP = NO
|
||||
GENERATE_CHI = NO
|
||||
BINARY_TOC = NO
|
||||
TOC_EXPAND = NO
|
||||
DISABLE_INDEX = NO
|
||||
ENUM_VALUES_PER_LINE = 4
|
||||
GENERATE_TREEVIEW = NO
|
||||
TREEVIEW_WIDTH = 250
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the LaTeX output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_LATEX = YES
|
||||
LATEX_OUTPUT = ps
|
||||
COMPACT_LATEX = NO
|
||||
PAPER_TYPE = a4
|
||||
EXTRA_PACKAGES =
|
||||
LATEX_HEADER =
|
||||
PDF_HYPERLINKS = YES
|
||||
USE_PDFLATEX = YES
|
||||
LATEX_BATCHMODE = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the RTF output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_RTF = YES
|
||||
RTF_OUTPUT = rtf
|
||||
COMPACT_RTF = NO
|
||||
RTF_HYPERLINKS = NO
|
||||
RTF_STYLESHEET_FILE =
|
||||
RTF_EXTENSIONS_FILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_MAN = NO
|
||||
MAN_OUTPUT = man
|
||||
MAN_EXTENSION = .3
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the preprocessor
|
||||
#---------------------------------------------------------------------------
|
||||
ENABLE_PREPROCESSING = NO
|
||||
MACRO_EXPANSION = NO
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
SEARCH_INCLUDES = YES
|
||||
INCLUDE_PATH =
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
PREDEFINED =
|
||||
EXPAND_AS_DEFINED =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration::addtions related to external references
|
||||
#---------------------------------------------------------------------------
|
||||
TAGFILES =
|
||||
GENERATE_TAGFILE =
|
||||
ALLEXTERNALS = NO
|
||||
PERL_PATH = /usr/bin/perl
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
HAVE_DOT = NO
|
||||
CLASS_GRAPH = YES
|
||||
COLLABORATION_GRAPH = YES
|
||||
INCLUDE_GRAPH = YES
|
||||
INCLUDED_BY_GRAPH = YES
|
||||
GRAPHICAL_HIERARCHY = YES
|
||||
DOT_PATH =
|
||||
MAX_DOT_GRAPH_WIDTH = 1024
|
||||
MAX_DOT_GRAPH_HEIGHT = 1024
|
||||
GENERATE_LEGEND = YES
|
||||
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 =
|
||||
|
||||
484
asterisk.c
484
asterisk.c
@@ -17,275 +17,48 @@
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/cli.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/ulaw.h>
|
||||
#include <asterisk/callerid.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/image.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <sched.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/select.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
#include "asterisk.h"
|
||||
|
||||
#define AST_MAX_CONNECTS 128
|
||||
#define NUM_MSGS 64
|
||||
|
||||
int option_verbose=0;
|
||||
int option_debug=0;
|
||||
int option_nofork=0;
|
||||
int option_quiet=0;
|
||||
int option_console=0;
|
||||
int option_highpriority=0;
|
||||
int option_remote=0;
|
||||
int option_exec=0;
|
||||
int fully_booted = 0;
|
||||
|
||||
static int ast_socket = -1; /* UNIX Socket for allowing remote control */
|
||||
static int ast_consock = -1; /* UNIX Socket for controlling another asterisk */
|
||||
static int mainpid;
|
||||
struct console {
|
||||
int fd; /* File descriptor */
|
||||
int p[2]; /* Pipe */
|
||||
pthread_t t; /* Thread of handler */
|
||||
};
|
||||
|
||||
struct console consoles[AST_MAX_CONNECTS];
|
||||
|
||||
char defaultlanguage[MAX_LANGUAGE] = DEFAULT_LANGUAGE;
|
||||
|
||||
static int fdprint(int fd, char *s)
|
||||
{
|
||||
return write(fd, s, strlen(s) + 1);
|
||||
}
|
||||
|
||||
static void network_verboser(char *s, int pos, int replace, int complete)
|
||||
{
|
||||
int x;
|
||||
for (x=0;x<AST_MAX_CONNECTS; x++) {
|
||||
if (consoles[x].fd > -1)
|
||||
fdprint(consoles[x].p[1], s);
|
||||
}
|
||||
}
|
||||
|
||||
static pthread_t lthread;
|
||||
|
||||
static void *netconsole(void *vconsole)
|
||||
{
|
||||
struct console *con = vconsole;
|
||||
char hostname[256];
|
||||
char tmp[512];
|
||||
int res;
|
||||
int max;
|
||||
fd_set rfds;
|
||||
|
||||
if (gethostname(hostname, sizeof(hostname)))
|
||||
strncpy(hostname, "<Unknown>", sizeof(hostname));
|
||||
snprintf(tmp, sizeof(tmp), "%s/%d/%s\n", hostname, mainpid, ASTERISK_VERSION);
|
||||
fdprint(con->fd, tmp);
|
||||
for(;;) {
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(con->fd, &rfds);
|
||||
FD_SET(con->p[0], &rfds);
|
||||
max = con->fd;
|
||||
if (con->p[0] > max)
|
||||
max = con->p[0];
|
||||
res = select(max + 1, &rfds, NULL, NULL, NULL);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "select returned < 0: %s\n", strerror(errno));
|
||||
continue;
|
||||
}
|
||||
if (FD_ISSET(con->fd, &rfds)) {
|
||||
res = read(con->fd, tmp, sizeof(tmp));
|
||||
if (res < 1) {
|
||||
break;
|
||||
}
|
||||
tmp[res] = 0;
|
||||
ast_cli_command(con->fd, tmp);
|
||||
}
|
||||
if (FD_ISSET(con->p[0], &rfds)) {
|
||||
res = read(con->p[0], tmp, sizeof(tmp));
|
||||
if (res < 1) {
|
||||
ast_log(LOG_ERROR, "read returned %d\n", res);
|
||||
break;
|
||||
}
|
||||
res = write(con->fd, tmp, res);
|
||||
if (res < 1)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Remote UNIX connection disconnected\n");
|
||||
close(con->fd);
|
||||
close(con->p[0]);
|
||||
close(con->p[1]);
|
||||
con->fd = -1;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *listener(void *unused)
|
||||
{
|
||||
struct sockaddr_un sun;
|
||||
int s;
|
||||
int len;
|
||||
int x;
|
||||
int flags;
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
for(;;) {
|
||||
len = sizeof(sun);
|
||||
s = accept(ast_socket, (struct sockaddr *)&sun, &len);
|
||||
if (s < 0) {
|
||||
ast_log(LOG_WARNING, "Accept retured %d: %s\n", s, strerror(errno));
|
||||
} else {
|
||||
for (x=0;x<AST_MAX_CONNECTS;x++) {
|
||||
if (consoles[x].fd < 0) {
|
||||
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, consoles[x].p)) {
|
||||
ast_log(LOG_ERROR, "Unable to create pipe: %s\n", strerror(errno));
|
||||
consoles[x].fd = -1;
|
||||
fdprint(s, "Server failed to create pipe\n");
|
||||
close(s);
|
||||
break;
|
||||
}
|
||||
flags = fcntl(consoles[x].p[1], F_GETFL);
|
||||
fcntl(consoles[x].p[1], F_SETFL, flags | O_NONBLOCK);
|
||||
consoles[x].fd = s;
|
||||
if (pthread_create(&consoles[x].t, &attr, netconsole, &consoles[x])) {
|
||||
ast_log(LOG_ERROR, "Unable to spawn thread to handle connection\n");
|
||||
consoles[x].fd = -1;
|
||||
fdprint(s, "Server failed to spawn thread\n");
|
||||
close(s);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (x >= AST_MAX_CONNECTS) {
|
||||
fdprint(s, "No more connections allowed\n");
|
||||
ast_log(LOG_WARNING, "No more connections allowed\n");
|
||||
close(s);
|
||||
} else if (consoles[x].fd > -1) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Remote UNIX connection\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int ast_makesocket(void)
|
||||
{
|
||||
struct sockaddr_un sun;
|
||||
int res;
|
||||
int x;
|
||||
for (x=0;x<AST_MAX_CONNECTS;x++)
|
||||
consoles[x].fd = -1;
|
||||
unlink(AST_SOCKET);
|
||||
ast_socket = socket(PF_LOCAL, SOCK_STREAM, 0);
|
||||
if (ast_socket < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to create control socket: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
memset(&sun, 0, sizeof(sun));
|
||||
sun.sun_family = AF_LOCAL;
|
||||
strncpy(sun.sun_path, AST_SOCKET, sizeof(sun.sun_path));
|
||||
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));
|
||||
close(ast_socket);
|
||||
ast_socket = -1;
|
||||
return -1;
|
||||
}
|
||||
res = listen(ast_socket, 2);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to listen on socket %s: %s\n", AST_SOCKET, strerror(errno));
|
||||
close(ast_socket);
|
||||
ast_socket = -1;
|
||||
return -1;
|
||||
}
|
||||
ast_register_verbose(network_verboser);
|
||||
pthread_create(<hread, NULL, listener, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ast_tryconnect(void)
|
||||
{
|
||||
struct sockaddr_un sun;
|
||||
int res;
|
||||
ast_consock = socket(PF_LOCAL, SOCK_STREAM, 0);
|
||||
if (ast_consock < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
memset(&sun, 0, sizeof(sun));
|
||||
sun.sun_family = AF_LOCAL;
|
||||
strncpy(sun.sun_path, AST_SOCKET, sizeof(sun.sun_path));
|
||||
res = connect(ast_consock, (struct sockaddr *)&sun, sizeof(sun));
|
||||
if (res) {
|
||||
close(ast_consock);
|
||||
ast_consock = -1;
|
||||
return 0;
|
||||
} else
|
||||
return 1;
|
||||
}
|
||||
#define HIGH_PRIORITY 1
|
||||
#define HIGH_PRIORITY_SCHED SCHED_RR
|
||||
|
||||
static void urg_handler(int num)
|
||||
{
|
||||
/* Called by soft_hangup to interrupt the select, read, or other
|
||||
system call. We don't actually need to do anything though. */
|
||||
if (option_debug)
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "Urgent handler\n");
|
||||
signal(num, urg_handler);
|
||||
return;
|
||||
}
|
||||
|
||||
static void hup_handler(int num)
|
||||
{
|
||||
if (option_verbose > 1)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "Received HUP signal -- Reloading configs\n");
|
||||
ast_module_reload();
|
||||
}
|
||||
|
||||
|
||||
static void pipe_handler(int num)
|
||||
{
|
||||
/* Ignore sigpipe */
|
||||
}
|
||||
static void set_title(char *text)
|
||||
{
|
||||
/* Set an X-term or screen title */
|
||||
if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
|
||||
fprintf(stdout, "\033]2;%s\007", text);
|
||||
}
|
||||
|
||||
static void set_icon(char *text)
|
||||
{
|
||||
if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
|
||||
fprintf(stdout, "\033]1;%s\007", text);
|
||||
}
|
||||
|
||||
static int set_priority(int pri)
|
||||
{
|
||||
struct sched_param sched;
|
||||
memset(&sched, 0, sizeof(sched));
|
||||
/* We set ourselves to a high priority, that we might pre-empt everything
|
||||
else. If your PBX has heavy activity on it, this is a good thing. */
|
||||
if (pri) {
|
||||
sched.sched_priority = 10;
|
||||
if (sched_setscheduler(0, SCHED_RR, &sched)) {
|
||||
sched.sched_priority = HIGH_PRIORITY;
|
||||
if (sched_setscheduler(0, HIGH_PRIORITY_SCHED, &sched)) {
|
||||
ast_log(LOG_WARNING, "Unable to set high priority\n");
|
||||
return -1;
|
||||
} else
|
||||
if (option_verbose)
|
||||
ast_verbose("Set to realtime thread\n");
|
||||
}
|
||||
} else {
|
||||
sched.sched_priority = 0;
|
||||
if (sched_setscheduler(0, SCHED_OTHER, &sched)) {
|
||||
@@ -298,26 +71,19 @@ static int set_priority(int pri)
|
||||
|
||||
static void quit_handler(int num)
|
||||
{
|
||||
static pthread_mutex_t quitlock = PTHREAD_MUTEX_INITIALIZER;
|
||||
char filename[80] = "";
|
||||
if (option_console || option_remote) {
|
||||
if (getenv("HOME"))
|
||||
snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
|
||||
if (strlen(filename))
|
||||
write_history(filename);
|
||||
rl_callback_handler_remove();
|
||||
}
|
||||
if (getenv("HOME"))
|
||||
snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
|
||||
/* Quit only once */
|
||||
pthread_mutex_lock(&quitlock);
|
||||
/* Called on exit */
|
||||
if (option_verbose && option_console)
|
||||
if (option_verbose)
|
||||
ast_verbose("Asterisk ending (%d).\n", num);
|
||||
else if (option_debug)
|
||||
ast_log(LOG_DEBUG, "Asterisk ending (%d).\n", num);
|
||||
if (ast_socket > -1)
|
||||
close(ast_socket);
|
||||
if (ast_consock > -1)
|
||||
close(ast_consock);
|
||||
if (ast_socket > -1)
|
||||
unlink(AST_SOCKET);
|
||||
|
||||
if (strlen(filename))
|
||||
write_history(filename);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@@ -355,39 +121,10 @@ static void consolehandler(char *s)
|
||||
fprintf(stdout, "\nUse \"quit\" to exit\n");
|
||||
}
|
||||
|
||||
|
||||
static char cmd[1024];
|
||||
|
||||
static void remoteconsolehandler(char *s)
|
||||
{
|
||||
/* Called when readline data is available */
|
||||
if (s && strlen(s))
|
||||
add_history(s);
|
||||
/* Give the console access to the shell */
|
||||
if (s) {
|
||||
if (s[0] == '!') {
|
||||
if (s[1])
|
||||
system(s+1);
|
||||
else
|
||||
system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
|
||||
} else
|
||||
strncpy(cmd, s, sizeof(cmd));
|
||||
if (!strcasecmp(s, "help"))
|
||||
fprintf(stdout, " !<command> Executes a given shell command\n");
|
||||
if (!strcasecmp(s, "quit"))
|
||||
quit_handler(0);
|
||||
} else
|
||||
fprintf(stdout, "\nUse \"quit\" to exit\n");
|
||||
}
|
||||
|
||||
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 int handle_quit(int fd, int argc, char *argv[])
|
||||
{
|
||||
if (argc != 1)
|
||||
@@ -398,137 +135,19 @@ static int handle_quit(int fd, int argc, char *argv[])
|
||||
|
||||
#define ASTERISK_PROMPT "*CLI> "
|
||||
|
||||
#define ASTERISK_PROMPT2 "%s*CLI> "
|
||||
|
||||
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 char *cli_generator(char *text, int state)
|
||||
{
|
||||
return ast_cli_generator(rl_line_buffer, text, state);
|
||||
}
|
||||
|
||||
static char *console_cli_generator(char *text, int state)
|
||||
{
|
||||
char buf[1024];
|
||||
int res;
|
||||
#if 0
|
||||
fprintf(stderr, "Searching for '%s', %s %d\n", rl_line_buffer, text, state);
|
||||
#endif
|
||||
snprintf(buf, sizeof(buf),"_COMMAND COMPLETE \"%s\" \"%s\" %d", rl_line_buffer, text, state);
|
||||
fdprint(ast_consock, buf);
|
||||
res = read(ast_consock, buf, sizeof(buf));
|
||||
buf[res] = '\0';
|
||||
#if 0
|
||||
printf("res is %d, buf is '%s'\n", res, buf);
|
||||
#endif
|
||||
if (strncmp(buf, "NULL", 4))
|
||||
return strdup(buf);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void ast_remotecontrol(char * data)
|
||||
{
|
||||
char buf[80];
|
||||
int res;
|
||||
int max;
|
||||
int lastpos = 0;
|
||||
fd_set rfds;
|
||||
char filename[80] = "";
|
||||
char *hostname;
|
||||
char *cpid;
|
||||
char *version;
|
||||
int pid;
|
||||
char tmp[80];
|
||||
read(ast_consock, buf, sizeof(buf));
|
||||
if (data) {
|
||||
write(ast_consock, data, strlen(data) + 1);
|
||||
return;
|
||||
}
|
||||
hostname = strtok(buf, "/");
|
||||
cpid = strtok(NULL, "/");
|
||||
version = strtok(NULL, "/");
|
||||
if (!version)
|
||||
version = "<Version Unknown>";
|
||||
strtok(hostname, ".");
|
||||
if (cpid)
|
||||
pid = atoi(cpid);
|
||||
else
|
||||
pid = -1;
|
||||
snprintf(tmp, sizeof(tmp), "set verbose atleast %d", option_verbose);
|
||||
fdprint(ast_consock, tmp);
|
||||
ast_verbose("Connected to Asterisk %s currently running on %s (pid = %d)\n", version, hostname, pid);
|
||||
snprintf(tmp, sizeof(tmp), ASTERISK_PROMPT2, hostname);
|
||||
if (getenv("HOME"))
|
||||
snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
|
||||
if (strlen(filename))
|
||||
read_history(filename);
|
||||
ast_cli_register(&quit);
|
||||
ast_cli_register(&astshutdown);
|
||||
rl_callback_handler_install(tmp, remoteconsolehandler);
|
||||
rl_completion_entry_function = (Function *)console_cli_generator;
|
||||
for(;;) {
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(ast_consock, &rfds);
|
||||
FD_SET(STDIN_FILENO, &rfds);
|
||||
max = ast_consock;
|
||||
if (STDIN_FILENO > max)
|
||||
max = STDIN_FILENO;
|
||||
res = select(max + 1, &rfds, NULL, NULL, NULL);
|
||||
if (res < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
ast_log(LOG_ERROR, "select failed: %s\n", strerror(errno));
|
||||
break;
|
||||
}
|
||||
if (FD_ISSET(STDIN_FILENO, &rfds)) {
|
||||
rl_callback_read_char();
|
||||
if (strlen(cmd)) {
|
||||
res = write(ast_consock, cmd, strlen(cmd) + 1);
|
||||
if (res < 1) {
|
||||
ast_log(LOG_WARNING, "Unable to write: %s\n", strerror(errno));
|
||||
break;
|
||||
}
|
||||
strcpy(cmd, "");
|
||||
}
|
||||
}
|
||||
if (FD_ISSET(ast_consock, &rfds)) {
|
||||
res = read(ast_consock, buf, sizeof(buf));
|
||||
if (res < 1)
|
||||
break;
|
||||
buf[res] = 0;
|
||||
if (!lastpos)
|
||||
write(STDOUT_FILENO, "\r", 2);
|
||||
write(STDOUT_FILENO, buf, res);
|
||||
if ((buf[res-1] == '\n') || (buf[res-2] == '\n')) {
|
||||
rl_forced_update_display();
|
||||
lastpos = 0;
|
||||
} else {
|
||||
lastpos = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("\nDisconnected from Asterisk server\n");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char c;
|
||||
fd_set rfds;
|
||||
int res;
|
||||
int pid;
|
||||
char filename[80] = "";
|
||||
char hostname[256];
|
||||
char * xarg = NULL;
|
||||
sigset_t sigs;
|
||||
|
||||
if (gethostname(hostname, sizeof(hostname)))
|
||||
strncpy(hostname, "<Unknown>", sizeof(hostname));
|
||||
mainpid = getpid();
|
||||
ast_ulaw_init();
|
||||
callerid_init();
|
||||
if (getenv("HOME"))
|
||||
snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
|
||||
/* Check if we're root */
|
||||
@@ -537,7 +156,7 @@ int main(int argc, char *argv[])
|
||||
exit(1);
|
||||
}
|
||||
/* Check for options */
|
||||
while((c=getopt(argc, argv, "fdvqprcx:")) != EOF) {
|
||||
while((c=getopt(argc, argv, "dvqpc")) != EOF) {
|
||||
switch(c) {
|
||||
case 'd':
|
||||
option_debug++;
|
||||
@@ -546,14 +165,6 @@ int main(int argc, char *argv[])
|
||||
case 'c':
|
||||
option_console++;
|
||||
option_nofork++;
|
||||
break;
|
||||
case 'f':
|
||||
option_nofork++;
|
||||
break;
|
||||
case 'r':
|
||||
option_remote++;
|
||||
option_nofork++;
|
||||
break;
|
||||
case 'p':
|
||||
option_highpriority++;
|
||||
break;
|
||||
@@ -564,60 +175,14 @@ int main(int argc, char *argv[])
|
||||
case 'q':
|
||||
option_quiet++;
|
||||
break;
|
||||
case 'x':
|
||||
option_exec++;
|
||||
xarg = optarg;
|
||||
break;
|
||||
case '?':
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (ast_tryconnect()) {
|
||||
/* One is already running */
|
||||
if (option_remote) {
|
||||
if (option_exec) {
|
||||
ast_remotecontrol(xarg);
|
||||
quit_handler(0);
|
||||
exit(0);
|
||||
}
|
||||
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);
|
||||
exit(0);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Asterisk already running on %s. Use 'asterisk -r' to connect.\n", AST_SOCKET);
|
||||
exit(1);
|
||||
}
|
||||
} else if (option_remote || option_exec) {
|
||||
ast_log(LOG_ERROR, "Unable to connect to remote asterisk\n");
|
||||
exit(1);
|
||||
}
|
||||
if (!option_verbose && !option_console && !option_debug) {
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
ast_log(LOG_ERROR, "Unable to fork(): %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
if (pid)
|
||||
exit(0);
|
||||
}
|
||||
ast_makesocket();
|
||||
sigemptyset(&sigs);
|
||||
sigaddset(&sigs, SIGHUP);
|
||||
sigaddset(&sigs, SIGTERM);
|
||||
sigaddset(&sigs, SIGINT);
|
||||
sigaddset(&sigs, SIGPIPE);
|
||||
sigaddset(&sigs, SIGWINCH);
|
||||
pthread_sigmask(SIG_BLOCK, &sigs, NULL);
|
||||
if (option_console || option_verbose || option_remote)
|
||||
ast_register_verbose(console_verboser);
|
||||
ast_register_verbose(console_verboser);
|
||||
/* Print a welcome message if desired */
|
||||
if (option_verbose || option_console) {
|
||||
ast_verbose( "Asterisk " ASTERISK_VERSION ", Copyright (C) 1999-2001 Linux Support Services, Inc.\n");
|
||||
ast_verbose( "Asterisk, Copyright (C) 1999 Mark Spencer\n");
|
||||
ast_verbose( "Written by Mark Spencer <markster@linux-support.net>\n");
|
||||
ast_verbose( "=========================================================================\n");
|
||||
}
|
||||
@@ -626,19 +191,14 @@ int main(int argc, char *argv[])
|
||||
signal(SIGURG, urg_handler);
|
||||
signal(SIGINT, quit_handler);
|
||||
signal(SIGTERM, quit_handler);
|
||||
signal(SIGHUP, hup_handler);
|
||||
signal(SIGPIPE, pipe_handler);
|
||||
if (set_priority(option_highpriority))
|
||||
exit(1);
|
||||
signal(SIGHUP, quit_handler);
|
||||
if (init_logger())
|
||||
exit(1);
|
||||
if (ast_image_init())
|
||||
exit(1);
|
||||
if (load_pbx())
|
||||
exit(1);
|
||||
if (load_modules())
|
||||
exit(1);
|
||||
if (init_framer())
|
||||
if (set_priority(option_highpriority))
|
||||
exit(1);
|
||||
/* We might have the option of showing a console, but for now just
|
||||
do nothing... */
|
||||
@@ -647,15 +207,9 @@ int main(int argc, char *argv[])
|
||||
if (option_verbose || option_console)
|
||||
ast_verbose( "Asterisk Ready.\n");
|
||||
fully_booted = 1;
|
||||
pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);
|
||||
ast_cli_register(&astshutdown);
|
||||
if (option_console) {
|
||||
/* Console stuff now... */
|
||||
/* Register our quit function */
|
||||
char title[256];
|
||||
set_icon("Asterisk");
|
||||
snprintf(title, sizeof(title), "Asterisk Console on '%s' (pid %d)", hostname, mainpid);
|
||||
set_title(title);
|
||||
ast_cli_register(&quit);
|
||||
consolethread = pthread_self();
|
||||
if (strlen(filename))
|
||||
|
||||
@@ -17,17 +17,14 @@
|
||||
#define DEFAULT_LANGUAGE "en"
|
||||
|
||||
#define AST_CONFIG_DIR "/etc/asterisk"
|
||||
#define AST_SOCKET "/var/run/asterisk.ctl"
|
||||
#define AST_MODULE_DIR "/usr/lib/asterisk/modules"
|
||||
#define AST_SPOOL_DIR "/var/spool/asterisk"
|
||||
#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_CONFIG_FILE "asterisk.conf"
|
||||
|
||||
#define AST_SOUNDS AST_VAR_DIR "/sounds"
|
||||
#define AST_IMAGES AST_VAR_DIR "/images"
|
||||
|
||||
/* Provided by module.c */
|
||||
extern int load_modules(void);
|
||||
@@ -35,6 +32,5 @@ extern int load_modules(void);
|
||||
extern int load_pbx(void);
|
||||
/* Provided by logger.c */
|
||||
extern int init_logger(void);
|
||||
/* Provided by frame.c */
|
||||
extern int init_framer(void);
|
||||
|
||||
#endif
|
||||
|
||||
24
audiofile.patch
Normal file
24
audiofile.patch
Normal file
@@ -0,0 +1,24 @@
|
||||
diff -uNr audiofile-0.1.9.old/libaudiofile/audiofile.c audiofile-0.1.9/libaudiofile/audiofile.c
|
||||
--- audiofile-0.1.9.old/libaudiofile/audiofile.c Fri Jul 23 12:57:56 1999
|
||||
+++ audiofile-0.1.9/libaudiofile/audiofile.c Fri Dec 10 18:43:30 1999
|
||||
@@ -488,6 +488,20 @@
|
||||
return afOpenVirtualFile(af_virtual_file_new_for_file(fp), mode, setup);
|
||||
}
|
||||
|
||||
+AFfilehandle afOpenFD(int fd, const char *mode, AFfilesetup setup)
|
||||
+{
|
||||
+ FILE *fp;
|
||||
+
|
||||
+ fp = fdopen(fd, mode);
|
||||
+ if (fp == NULL)
|
||||
+ {
|
||||
+ _af_error(AF_BAD_OPEN);
|
||||
+ return AF_NULL_FILEHANDLE;
|
||||
+ }
|
||||
+
|
||||
+ return afOpenVirtualFile(af_virtual_file_new_for_file(fp), mode, setup);
|
||||
+}
|
||||
+
|
||||
int afGetFileFormat (AFfilehandle file, int *version)
|
||||
{
|
||||
assert(file);
|
||||
531
callerid.c
531
callerid.c
@@ -1,531 +0,0 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* CallerID Generation support
|
||||
*
|
||||
* Copyright (C) 2001, Linux Support Services, Inc.
|
||||
*
|
||||
* 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 <time.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include <asterisk/ulaw.h>
|
||||
#include <asterisk/callerid.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/fskmodem.h>
|
||||
#include "sas.h"
|
||||
#include "cas.h"
|
||||
|
||||
|
||||
struct callerid_state {
|
||||
fsk_data fskd;
|
||||
char rawdata[256];
|
||||
short oldstuff[160];
|
||||
int oldlen;
|
||||
int pos;
|
||||
int type;
|
||||
int cksum;
|
||||
char name[64];
|
||||
char number[64];
|
||||
int flags;
|
||||
int sawflag;
|
||||
int len;
|
||||
};
|
||||
|
||||
static float dr[4], di[4];
|
||||
static float clidsb = 8000.0 / 1200.0;
|
||||
|
||||
#define CALLERID_SPACE 2200.0 /* 2200 hz for "0" */
|
||||
#define CALLERID_MARK 1200.0 /* 1200 hz for "1" */
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
struct callerid_state *callerid_new(void)
|
||||
{
|
||||
struct callerid_state *cid;
|
||||
cid = malloc(sizeof(struct callerid_state));
|
||||
memset(cid, 0, sizeof(struct callerid_state));
|
||||
if (cid) {
|
||||
cid->fskd.spb = 7; /* 1200 baud */
|
||||
cid->fskd.hdlc = 0; /* Async */
|
||||
cid->fskd.nbit = 8; /* 8 bits */
|
||||
cid->fskd.nstop = 1; /* 1 stop bit */
|
||||
cid->fskd.paridad = 0; /* No parity */
|
||||
cid->fskd.bw=1; /* Filter 800 Hz */
|
||||
cid->fskd.f_mark_idx = 2; /* 1200 Hz */
|
||||
cid->fskd.f_space_idx = 3; /* 2200 Hz */
|
||||
cid->fskd.pcola = 0; /* No clue */
|
||||
cid->fskd.cont = 0; /* Digital PLL reset */
|
||||
cid->fskd.x0 = 0.0;
|
||||
cid->fskd.state = 0;
|
||||
memset(cid->name, 0, sizeof(cid->name));
|
||||
memset(cid->number, 0, sizeof(cid->number));
|
||||
cid->flags = CID_UNKNOWN_NAME | CID_UNKNOWN_NUMBER;
|
||||
cid->pos = 0;
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Out of memory\n");
|
||||
return cid;
|
||||
}
|
||||
|
||||
void callerid_get(struct callerid_state *cid, char **name, char **number, int *flags)
|
||||
{
|
||||
*flags = cid->flags;
|
||||
if (cid->flags & (CID_UNKNOWN_NAME | CID_PRIVATE_NUMBER))
|
||||
*name = NULL;
|
||||
else
|
||||
*name = cid->name;
|
||||
if (cid->flags & (CID_UNKNOWN_NUMBER | CID_PRIVATE_NUMBER))
|
||||
*number = NULL;
|
||||
else
|
||||
*number = cid->number;
|
||||
}
|
||||
|
||||
int ast_callerid_gen_cas(unsigned char *outbuf, 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;
|
||||
}
|
||||
while(len) {
|
||||
cnt = len;
|
||||
if (cnt > sizeof(cas))
|
||||
cnt = sizeof(cas);
|
||||
memcpy(outbuf + pos, cas, cnt);
|
||||
pos += cnt;
|
||||
len -= cnt;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len)
|
||||
{
|
||||
int mylen = len;
|
||||
int olen;
|
||||
int b = 'X';
|
||||
int res;
|
||||
int x;
|
||||
short *buf = malloc(2 * len + cid->oldlen);
|
||||
short *obuf = buf;
|
||||
if (!buf) {
|
||||
ast_log(LOG_WARNING, "Out of memory\n");
|
||||
return -1;
|
||||
}
|
||||
memset(buf, 0, 2 * len + cid->oldlen);
|
||||
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]];
|
||||
while(mylen >= 80) {
|
||||
olen = mylen;
|
||||
res = fsk_serie(&cid->fskd, buf, &mylen, &b);
|
||||
if (mylen < 0) {
|
||||
ast_log(LOG_ERROR, "fsk_serie made mylen < 0 (%d)\n", mylen);
|
||||
return -1;
|
||||
}
|
||||
buf += (olen - mylen);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_NOTICE, "fsk_serie failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (res == 1) {
|
||||
/* Ignore invalid bytes */
|
||||
if (b > 0xff)
|
||||
continue;
|
||||
switch(cid->sawflag) {
|
||||
case 0: /* Look for flag */
|
||||
if (b == 'U')
|
||||
cid->sawflag = 2;
|
||||
break;
|
||||
case 2: /* Get lead-in */
|
||||
if ((b == 0x04) || (b == 0x80)) {
|
||||
cid->type = b;
|
||||
cid->sawflag = 3;
|
||||
cid->cksum = b;
|
||||
}
|
||||
break;
|
||||
case 3: /* Get length */
|
||||
/* Not a lead in. We're ready */
|
||||
cid->sawflag = 4;
|
||||
cid->len = b;
|
||||
cid->pos = 0;
|
||||
cid->cksum += b;
|
||||
break;
|
||||
case 4: /* Retrieve message */
|
||||
if (cid->pos >= 128) {
|
||||
ast_log(LOG_WARNING, "Caller ID too long???\n");
|
||||
return -1;
|
||||
}
|
||||
cid->rawdata[cid->pos++] = b;
|
||||
cid->len--;
|
||||
cid->cksum += b;
|
||||
if (!cid->len) {
|
||||
cid->rawdata[cid->pos] = '\0';
|
||||
cid->sawflag = 5;
|
||||
}
|
||||
break;
|
||||
case 5: /* Check checksum */
|
||||
if (b != (256 - (cid->cksum & 0xff))) {
|
||||
ast_log(LOG_NOTICE, "Caller*ID failed checksum\n");
|
||||
/* Try again */
|
||||
cid->sawflag = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
strcpy(cid->number, "");
|
||||
strcpy(cid->name, "");
|
||||
/* If we get this far we're fine. */
|
||||
if (cid->type == 0x80) {
|
||||
/* MDMF */
|
||||
/* Go through each element and process */
|
||||
for (x=0;x< cid->pos;) {
|
||||
switch(cid->rawdata[x++]) {
|
||||
case 1:
|
||||
/* Date */
|
||||
break;
|
||||
case 2: /* Number */
|
||||
case 4: /* Number */
|
||||
res = cid->rawdata[x];
|
||||
if (res > 32) {
|
||||
ast_log(LOG_NOTICE, "Truncating long caller ID number from %d bytes to 32\n", cid->rawdata[x]);
|
||||
res = 32;
|
||||
}
|
||||
memcpy(cid->number, cid->rawdata + x + 1, res);
|
||||
/* Null terminate */
|
||||
cid->number[res] = '\0';
|
||||
break;
|
||||
case 7: /* Name */
|
||||
case 8: /* Name */
|
||||
res = cid->rawdata[x];
|
||||
if (res > 32) {
|
||||
ast_log(LOG_NOTICE, "Truncating long caller ID name from %d bytes to 32\n", cid->rawdata[x]);
|
||||
res = 32;
|
||||
}
|
||||
memcpy(cid->name, cid->rawdata + x + 1, res);
|
||||
cid->name[res] = '\0';
|
||||
break;
|
||||
default:
|
||||
ast_log(LOG_NOTICE, "Unknown IE %d\n", cid->rawdata[x-1]);
|
||||
}
|
||||
x += cid->rawdata[x];
|
||||
x++;
|
||||
}
|
||||
} else {
|
||||
/* SDMF */
|
||||
strncpy(cid->number, cid->rawdata + 8, sizeof(cid->number));
|
||||
}
|
||||
/* Update flags */
|
||||
cid->flags = 0;
|
||||
if (!strcmp(cid->number, "P")) {
|
||||
strcpy(cid->number, "");
|
||||
cid->flags |= CID_PRIVATE_NUMBER;
|
||||
} else if (!strcmp(cid->number, "O") || !strlen(cid->number)) {
|
||||
strcpy(cid->number, "");
|
||||
cid->flags |= CID_UNKNOWN_NUMBER;
|
||||
}
|
||||
if (!strcmp(cid->name, "P")) {
|
||||
strcpy(cid->name, "");
|
||||
cid->flags |= CID_PRIVATE_NAME;
|
||||
} else if (!strcmp(cid->name, "O") || !strlen(cid->name)) {
|
||||
strcpy(cid->name, "");
|
||||
cid->flags |= CID_UNKNOWN_NAME;
|
||||
}
|
||||
return 1;
|
||||
break;
|
||||
default:
|
||||
ast_log(LOG_ERROR, "Dunno what to do with a digit in sawflag %d\n", cid->sawflag);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mylen) {
|
||||
memcpy(cid->oldstuff, buf, mylen * 2);
|
||||
cid->oldlen = mylen * 2;
|
||||
} else
|
||||
cid->oldlen = 0;
|
||||
free(obuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void callerid_free(struct callerid_state *cid)
|
||||
{
|
||||
free(cid);
|
||||
}
|
||||
|
||||
static void callerid_genmsg(char *msg, int size, char *number, char *name, int flags)
|
||||
{
|
||||
time_t t;
|
||||
struct tm *tm;
|
||||
char *ptr;
|
||||
int res;
|
||||
int i,x;
|
||||
/* Get the time */
|
||||
time(&t);
|
||||
tm = localtime(&t);
|
||||
|
||||
ptr = msg;
|
||||
|
||||
/* Format time and message header */
|
||||
res = snprintf(ptr, size, "\001\010%02d%02d%02d%02d", tm->tm_mon + 1,
|
||||
tm->tm_mday, tm->tm_hour, tm->tm_min);
|
||||
size -= res;
|
||||
ptr += res;
|
||||
if (!number || !strlen(number) || (flags & CID_UNKNOWN_NUMBER)) {
|
||||
/* Indicate number not known */
|
||||
res = snprintf(ptr, size, "\004\001O");
|
||||
size -= res;
|
||||
ptr += res;
|
||||
} else if (flags & CID_PRIVATE_NUMBER) {
|
||||
/* Indicate number is private */
|
||||
res = snprintf(ptr, size, "\004\001P");
|
||||
size -= res;
|
||||
ptr += res;
|
||||
} else {
|
||||
/* Send up to 10 digits of number MAX */
|
||||
i = strlen(number);
|
||||
if (i > 10) i = 10;
|
||||
res = snprintf(ptr, size, "\002%c", i);
|
||||
size -= res;
|
||||
ptr += res;
|
||||
for (x=0;x<i;x++)
|
||||
ptr[x] = number[x];
|
||||
ptr[i] = '\0';
|
||||
ptr += i;
|
||||
size -= i;
|
||||
}
|
||||
|
||||
if (!name || !strlen(name) || (flags & CID_UNKNOWN_NAME)) {
|
||||
/* Indicate name not known */
|
||||
res = snprintf(ptr, size, "\010\001O");
|
||||
size -= res;
|
||||
ptr += res;
|
||||
} else if (flags & CID_PRIVATE_NAME) {
|
||||
/* Indicate name is private */
|
||||
res = snprintf(ptr, size, "\010\001P");
|
||||
size -= res;
|
||||
ptr += res;
|
||||
} else {
|
||||
/* Send up to 10 digits of number MAX */
|
||||
i = strlen(name);
|
||||
if (i > 16) i = 16;
|
||||
res = snprintf(ptr, size, "\007%c", i);
|
||||
size -= res;
|
||||
ptr += res;
|
||||
for (x=0;x<i;x++)
|
||||
ptr[x] = name[x];
|
||||
ptr[i] = '\0';
|
||||
ptr += i;
|
||||
size -= i;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
int x, sum;
|
||||
/* Initial carriers (real/imaginary) */
|
||||
float cr = 1.0;
|
||||
float ci = 0.0;
|
||||
float scont = 0.0;
|
||||
char msg[256];
|
||||
callerid_genmsg(msg, sizeof(msg), number, name, flags);
|
||||
if (!callwaiting) {
|
||||
/* Wait a half a second */
|
||||
for (x=0;x<4000;x++)
|
||||
PUT_BYTE(0x7f);
|
||||
/* Transmit 30 0x55's (looks like a square wave) for channel seizure */
|
||||
for (x=0;x<30;x++)
|
||||
PUT_CLID(0x55);
|
||||
}
|
||||
/* Send 150ms of callerid marks */
|
||||
for (x=0;x<150;x++)
|
||||
PUT_CLID_MARKMS;
|
||||
/* Send 0x80 indicating MDMF format */
|
||||
PUT_CLID(0x80);
|
||||
/* Put length of whole message */
|
||||
PUT_CLID(strlen(msg));
|
||||
sum = 0x80 + strlen(msg);
|
||||
/* Put each character of message and update checksum */
|
||||
for (x=0;x<strlen(msg); x++) {
|
||||
PUT_CLID(msg[x]);
|
||||
sum += msg[x];
|
||||
}
|
||||
/* Send 2's compliment of sum */
|
||||
PUT_CLID(256 - (sum & 255));
|
||||
/* Send 50 more ms of marks */
|
||||
for (x=0;x<50;x++)
|
||||
PUT_CLID_MARKMS;
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
void ast_shrink_phone_number(char *n)
|
||||
{
|
||||
int x,y=0;
|
||||
for (x=0;n[x];x++)
|
||||
if (!strchr("( )-.", n[x]))
|
||||
n[y++] = n[x];
|
||||
n[y] = '\0';
|
||||
}
|
||||
|
||||
int ast_isphonenumber(char *n)
|
||||
{
|
||||
int x;
|
||||
if (!n || !strlen(n))
|
||||
return 0;
|
||||
for (x=0;n[x];x++)
|
||||
if (!strchr("0123456789", n[x]))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ast_callerid_parse(char *instr, char **name, char **location)
|
||||
{
|
||||
char *ns, *ne;
|
||||
char *ls, *le;
|
||||
char tmp[256];
|
||||
/* Try for "name" <location> format or
|
||||
name <location> format */
|
||||
if ((ls = strchr(instr, '<')) && (le = strchr(ls, '>'))) {
|
||||
/* Found the location */
|
||||
*le = '\0';
|
||||
*ls = '\0';
|
||||
*location = ls + 1;
|
||||
if ((ns = strchr(instr, '\"')) && (ne = strchr(ns + 1, '\"'))) {
|
||||
/* Get name out of quotes */
|
||||
*ns = '\0';
|
||||
*ne = '\0';
|
||||
*name = ns + 1;
|
||||
return 0;
|
||||
} else {
|
||||
/* Just trim off any trailing spaces */
|
||||
*name = instr;
|
||||
while(strlen(instr) && (instr[strlen(instr) - 1] < 33))
|
||||
instr[strlen(instr) - 1] = '\0';
|
||||
/* And leading spaces */
|
||||
while(**name && (**name < 33))
|
||||
name++;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
strncpy(tmp, instr, sizeof(tmp));
|
||||
ast_shrink_phone_number(tmp);
|
||||
if (ast_isphonenumber(tmp)) {
|
||||
/* Assume it's just a location */
|
||||
*name = NULL;
|
||||
*location = instr;
|
||||
} else {
|
||||
/* Assume it's just a name */
|
||||
*name = instr;
|
||||
*location = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int __ast_callerid_generate(unsigned char *buf, char *callerid, int callwaiting)
|
||||
{
|
||||
char tmp[256];
|
||||
char *n, *l;
|
||||
if (!callerid)
|
||||
return callerid_generate(buf, NULL, NULL, 0, callwaiting);
|
||||
strncpy(tmp, callerid, sizeof(tmp));
|
||||
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);
|
||||
}
|
||||
if (l)
|
||||
ast_shrink_phone_number(l);
|
||||
if (!ast_isphonenumber(l))
|
||||
return callerid_generate(buf, NULL, n, 0, callwaiting);
|
||||
return callerid_generate(buf, l, n, 0, callwaiting);
|
||||
}
|
||||
|
||||
int ast_callerid_generate(unsigned char *buf, char *callerid)
|
||||
{
|
||||
return __ast_callerid_generate(buf, callerid, 0);
|
||||
}
|
||||
|
||||
int ast_callerid_callwaiting_generate(unsigned char *buf, char *callerid)
|
||||
{
|
||||
return __ast_callerid_generate(buf, callerid, 1);
|
||||
}
|
||||
58
cas.h
58
cas.h
@@ -1,58 +0,0 @@
|
||||
/* cas.h: Generated from frequencies 2130 and 2750
|
||||
by gensound. 800 samples */
|
||||
static unsigned char cas[800] = {
|
||||
255, 177, 60, 69, 189, 105, 95, 95, 90, 188, 78, 56, 180, 207, 48,
|
||||
196, 191, 63, 117, 226, 224, 207, 60, 229, 180, 56, 66, 176, 80, 60,
|
||||
194, 226, 103, 101, 74, 189, 223, 50, 190, 187, 50, 241, 186, 72, 90,
|
||||
237, 238, 198, 63, 76, 177, 72, 54, 180, 215, 57, 207, 214, 120, 251,
|
||||
66, 196, 193, 49, 219, 178, 57, 73, 185, 91, 83, 124, 103, 191, 75,
|
||||
60, 179, 223, 48, 190, 191, 59, 241, 211, 244, 220, 63, 216, 184, 54,
|
||||
74, 175, 72, 59, 189, 230, 84, 113, 83, 191, 255, 53, 187, 190, 48,
|
||||
217, 185, 64, 89, 214, 243, 205, 64, 87, 179, 65, 57, 178, 233, 55,
|
||||
199, 208, 90, 122, 74, 196, 201, 50, 206, 180, 53, 78, 183, 79, 77,
|
||||
222, 119, 199, 74, 64, 179, 111, 49, 186, 194, 55, 222, 203, 101, 234,
|
||||
69, 210, 187, 54, 84, 175, 64, 60, 185, 246, 75, 236, 96, 196, 100,
|
||||
56, 185, 196, 47, 204, 184, 60, 91, 203, 117, 218, 69, 104, 182, 62,
|
||||
60, 176, 104, 54, 191, 207, 77, 252, 84, 199, 210, 52, 200, 183, 51,
|
||||
89, 180, 72, 74, 207, 255, 207, 74, 72, 180, 89, 51, 183, 200, 52,
|
||||
210, 199, 84, 252, 77, 207, 191, 54, 104, 176, 60, 62, 182, 104, 69,
|
||||
218, 117, 203, 91, 60, 184, 204, 47, 196, 185, 56, 100, 196, 96, 236,
|
||||
75, 246, 185, 60, 64, 175, 84, 54, 187, 210, 69, 234, 101, 203, 222,
|
||||
55, 194, 186, 49, 111, 179, 64, 74, 199, 119, 222, 77, 79, 183, 78,
|
||||
53, 180, 206, 50, 201, 196, 74, 122, 90, 208, 199, 55, 233, 178, 57,
|
||||
65, 179, 87, 64, 205, 243, 214, 89, 64, 185, 217, 48, 190, 187, 53,
|
||||
255, 191, 83, 113, 84, 230, 189, 59, 72, 175, 74, 54, 184, 216, 63,
|
||||
220, 244, 211, 241, 59, 191, 190, 48, 223, 179, 60, 75, 191, 103, 124,
|
||||
83, 91, 185, 73, 57, 178, 219, 49, 193, 196, 66, 251, 120, 214, 207,
|
||||
57, 215, 180, 54, 72, 177, 76, 63, 198, 238, 237, 90, 72, 186, 241,
|
||||
50, 187, 190, 50, 223, 189, 74, 101, 103, 226, 194, 60, 80, 176, 66,
|
||||
56, 180, 229, 60, 207, 224, 226, 117, 63, 191, 196, 48, 207, 180, 56,
|
||||
78, 188, 90, 95, 95, 105, 189, 69, 60, 177, 255, 49, 188, 197, 61,
|
||||
233, 223, 223, 218, 60, 206, 184, 52, 79, 176, 68, 63, 191, 245, 98,
|
||||
96, 79, 188, 101, 52, 184, 194, 48, 208, 188, 66, 98, 231, 229, 202,
|
||||
61, 95, 178, 62, 59, 178, 113, 58, 200, 218, 109, 110, 70, 191, 204,
|
||||
49, 200, 182, 52, 87, 185, 79, 86, 248, 123, 194, 68, 65, 177, 91,
|
||||
50, 185, 201, 57, 219, 211, 252, 231, 63, 203, 188, 51, 95, 176, 62,
|
||||
63, 187, 113, 83, 116, 92, 191, 88, 56, 182, 202, 47, 200, 187, 61,
|
||||
102, 212, 241, 211, 63, 255, 181, 59, 62, 176, 89, 57, 192, 217, 86,
|
||||
115, 77, 192, 215, 51, 193, 185, 50, 105, 183, 71, 80, 218, 250, 202,
|
||||
68, 73, 178, 78, 52, 181, 206, 55, 207, 205, 94, 247, 71, 202, 192,
|
||||
51, 239, 177, 58, 66, 183, 94, 75, 229, 106, 197, 82, 59, 182, 212,
|
||||
47, 192, 188, 57, 118, 203, 108, 224, 68, 228, 184, 57, 68, 175, 76,
|
||||
56, 188, 219, 75, 245, 90, 197, 232, 54, 190, 188, 48, 232, 182, 63,
|
||||
79, 205, 124, 212, 71, 82, 180, 72, 55, 179, 217, 52, 200, 202, 79,
|
||||
255, 79, 202, 200, 52, 217, 179, 55, 72, 180, 82, 71, 212, 124, 205,
|
||||
79, 63, 182, 232, 48, 188, 190, 54, 232, 197, 90, 245, 75, 219, 188,
|
||||
56, 76, 175, 68, 57, 184, 228, 68, 224, 108, 203, 118, 57, 188, 192,
|
||||
47, 212, 182, 59, 82, 197, 106, 229, 75, 94, 183, 66, 58, 177, 239,
|
||||
51, 192, 202, 71, 247, 94, 205, 207, 55, 206, 181, 52, 78, 178, 73,
|
||||
68, 202, 250, 218, 80, 71, 183, 105, 50, 185, 193, 51, 215, 192, 77,
|
||||
115, 86, 217, 192, 57, 89, 176, 62, 59, 181, 255, 63, 211, 241, 212,
|
||||
102, 61, 187, 200, 47, 202, 182, 56, 88, 191, 92, 116, 83, 113, 187,
|
||||
63, 62, 176, 95, 51, 188, 203, 63, 231, 252, 211, 219, 57, 201, 185,
|
||||
50, 91, 177, 65, 68, 194, 123, 248, 86, 79, 185, 87, 52, 182, 200,
|
||||
49, 204, 191, 70, 110, 109, 218, 200, 58, 113, 178, 59, 62, 178, 95,
|
||||
61, 202, 229, 231, 98, 66, 188, 208, 48, 194, 184, 52, 101, 188, 79,
|
||||
96, 98, 245, 191, 63, 68, 176, 79, 52, 184, 206, 60, 218, 223, 223,
|
||||
233, 61, 197, 188, 49,
|
||||
};
|
||||
@@ -12,47 +12,22 @@
|
||||
#
|
||||
|
||||
CHANNEL_LIBS=chan_vofr.so chan_modem.so \
|
||||
chan_modem_aopen.so chan_iax.so chan_oss.so \
|
||||
chan_modem_bestdata.so chan_modem_i4l.so
|
||||
chan_modem_aopen.so chan_iax.so chan_oss.so
|
||||
|
||||
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")
|
||||
CFLAGS+=$(shell [ -f /usr/lib/libpri.so.1 ] && echo " -DZAPATA_PRI")
|
||||
ZAPPRI=$(shell [ -f /usr/lib/libpri.so.1 ] && echo "-lpri")
|
||||
|
||||
CFLAGS+=#-DVOFRDUMPER
|
||||
|
||||
ZAPDIR=/usr/lib
|
||||
|
||||
CHANNEL_LIBS+=$(shell [ -f $(ZAPDIR)/libzap.a ] && echo "chan_zap.so")
|
||||
|
||||
CFLAGS+=$(shell [ -f $(ZAPDIR)/libzap.a ] && echo "-I$(ZAPDIR)")
|
||||
|
||||
all: $(CHANNEL_LIBS)
|
||||
|
||||
clean:
|
||||
rm -f *.so *.o
|
||||
rm -f busy.h ringtone.h gentone
|
||||
|
||||
%.so : %.o
|
||||
$(CC) -shared -Xlinker -x -o $@ $<
|
||||
|
||||
gentone: gentone.c
|
||||
$(CC) -o gentone gentone.c -lm
|
||||
|
||||
busy.h: gentone
|
||||
./gentone busy 480 620
|
||||
|
||||
ringtone.h: gentone
|
||||
./gentone ringtone 440 480
|
||||
|
||||
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_modem.so : chan_modem.o
|
||||
# $(CC) -rdynamic -shared -Xlinker -x -o $@ $<
|
||||
|
||||
|
||||
566
channels/alaw.h
566
channels/alaw.h
@@ -1,566 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 1997 Kolja Waschk
|
||||
|
||||
Name: alaw.h
|
||||
Version: 1.0
|
||||
Author: Marco Budde
|
||||
Description: Converts a-law signals to signed linear signals and
|
||||
vice versa.
|
||||
|
||||
|
||||
This file is part of isdn2h323.
|
||||
|
||||
This is public domain, but if you take more from this source than
|
||||
just the idea, it would be neat to see my name mentioned in your
|
||||
source or readme.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#define ALAW2INT(x) alaw2int[x]
|
||||
#define INT2ALAW(x) int2alaw[(x>>4)+4096]
|
||||
|
||||
|
||||
// table to convert unsigned a-law bytes to signed linear integers
|
||||
|
||||
const int alaw2int[256] = {
|
||||
-5504,5504,-344,344,-22016,22016,-1376,1376,-2752,2752,-88,88,-11008,11008,
|
||||
-688,688,-7552,7552,-472,472,-30208,30208,-1888,1888,-3776,3776,-216,216,
|
||||
-15104,15104,-944,944,-4480,4480,-280,280,-17920,17920,-1120,1120,-2240,2240,
|
||||
-24, 24,-8960,8960,-560,560,-6528,6528,-408,408,-26112,26112,-1632,1632,
|
||||
-3264,3264,-152,152,-13056,13056,-816,816,-6016,6016,-376,376,-24064,24064,
|
||||
-1504,1504,-3008,3008,-120,120,-12032,12032,-752,752,-8064,8064,-504,504,
|
||||
-32256,32256,-2016,2016,-4032,4032,-248,248,-16128,16128,-1008,1008,-4992,
|
||||
4992,-312,312,-19968,19968,-1248,1248,-2496,2496,-56,56,-9984,9984,-624,624,
|
||||
-7040,7040,-440,440,-28160,28160,-1760,1760,-3520,3520,-184,184,-14080,14080,
|
||||
-880,880,-5248,5248,-328,328,-20992,20992,-1312,1312,-2624,2624,-72,72,
|
||||
-10496,10496,-656,656,-7296,7296,-456,456,-29184,29184,-1824,1824,-3648,3648,
|
||||
-200,200,-14592,14592,-912,912,-4224,4224,-264,264,-16896,16896,-1056,1056,
|
||||
-2112,2112, -8, 8,-8448,8448,-528,528,-6272,6272,-392,392,-25088,25088,
|
||||
-1568,1568,-3136,3136,-136,136,-12544,12544,-784,784,-5760,5760,-360,360,
|
||||
-23040,23040,-1440,1440,-2880,2880,-104,104,-11520,11520,-720,720,-7808,7808,
|
||||
-488,488,-31232,31232,-1952,1952,-3904,3904,-232,232,-15616,15616,-976,976,
|
||||
-4736,4736,-296,296,-18944,18944,-1184,1184,-2368,2368,-40,40,-9472,9472,
|
||||
-592,592,-6784,6784,-424,424,-27136,27136,-1696,1696,-3392,3392,-168,168,
|
||||
-13568,13568,-848,848
|
||||
};
|
||||
|
||||
|
||||
// table to convert linear shorts to a-law bytes
|
||||
// shift the integer to be 12+1 bit first, then add 4096 to get
|
||||
// the right index
|
||||
|
||||
const unsigned char int2alaw[8192] = {
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
|
||||
212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
|
||||
212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
|
||||
212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
|
||||
212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
|
||||
20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
|
||||
20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
|
||||
20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
|
||||
20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
|
||||
148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
|
||||
148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
|
||||
148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
|
||||
148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
|
||||
116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
|
||||
116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
|
||||
116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
|
||||
116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
|
||||
244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
|
||||
244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
|
||||
244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
|
||||
244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
|
||||
52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
|
||||
52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
|
||||
52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
|
||||
52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
|
||||
180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
|
||||
180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
|
||||
180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
|
||||
180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
|
||||
68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
|
||||
68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
|
||||
68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
|
||||
68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
|
||||
196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
|
||||
196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
|
||||
196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
|
||||
196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
|
||||
132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
|
||||
132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
|
||||
132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
|
||||
100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
|
||||
100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
|
||||
100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
|
||||
100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
|
||||
228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
|
||||
228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
|
||||
228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
|
||||
228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
|
||||
164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
|
||||
164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
|
||||
164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
|
||||
164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
|
||||
92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
|
||||
92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
|
||||
220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,
|
||||
220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,
|
||||
28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,
|
||||
28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,
|
||||
156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,
|
||||
156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,
|
||||
124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,
|
||||
124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,
|
||||
252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,
|
||||
252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,
|
||||
60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,
|
||||
60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,
|
||||
188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,
|
||||
188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,
|
||||
76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,
|
||||
76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,
|
||||
204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,
|
||||
204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,
|
||||
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
||||
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
||||
140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,
|
||||
140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,
|
||||
108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,
|
||||
108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,
|
||||
236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,
|
||||
236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,
|
||||
44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,
|
||||
44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,
|
||||
172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
|
||||
172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
|
||||
80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
|
||||
208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
|
||||
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
|
||||
144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
|
||||
112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
|
||||
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
|
||||
48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
|
||||
176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
|
||||
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
|
||||
192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
|
||||
96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
|
||||
224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
|
||||
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
|
||||
160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
|
||||
88,88,88,88,88,88,88,88,216,216,216,216,216,216,216,216,
|
||||
24,24,24,24,24,24,24,24,152,152,152,152,152,152,152,152,
|
||||
120,120,120,120,120,120,120,120,248,248,248,248,248,248,248,248,
|
||||
56,56,56,56,56,56,56,56,184,184,184,184,184,184,184,184,
|
||||
72,72,72,72,72,72,72,72,200,200,200,200,200,200,200,200,
|
||||
8,8,8,8,8,8,8,8,136,136,136,136,136,136,136,136,
|
||||
104,104,104,104,104,104,104,104,232,232,232,232,232,232,232,232,
|
||||
40,40,40,40,40,40,40,40,168,168,168,168,168,168,168,168,
|
||||
86,86,86,86,214,214,214,214,22,22,22,22,150,150,150,150,
|
||||
118,118,118,118,246,246,246,246,54,54,54,54,182,182,182,182,
|
||||
70,70,70,70,198,198,198,198,6,6,6,6,134,134,134,134,
|
||||
102,102,102,102,230,230,230,230,38,38,38,38,166,166,166,166,
|
||||
94,94,222,222,30,30,158,158,126,126,254,254,62,62,190,190,
|
||||
78,78,206,206,14,14,142,142,110,110,238,238,46,46,174,174,
|
||||
82,210,18,146,114,242,50,178,66,194,2,130,98,226,34,162,
|
||||
90,218,26,154,122,250,58,186,74,202,10,138,106,234,42,170,
|
||||
171,43,235,107,139,11,203,75,187,59,251,123,155,27,219,91,
|
||||
163,35,227,99,131,3,195,67,179,51,243,115,147,19,211,83,
|
||||
175,175,47,47,239,239,111,111,143,143,15,15,207,207,79,79,
|
||||
191,191,63,63,255,255,127,127,159,159,31,31,223,223,95,95,
|
||||
167,167,167,167,39,39,39,39,231,231,231,231,103,103,103,103,
|
||||
135,135,135,135,7,7,7,7,199,199,199,199,71,71,71,71,
|
||||
183,183,183,183,55,55,55,55,247,247,247,247,119,119,119,119,
|
||||
151,151,151,151,23,23,23,23,215,215,215,215,87,87,87,87,
|
||||
169,169,169,169,169,169,169,169,41,41,41,41,41,41,41,41,
|
||||
233,233,233,233,233,233,233,233,105,105,105,105,105,105,105,105,
|
||||
137,137,137,137,137,137,137,137,9,9,9,9,9,9,9,9,
|
||||
201,201,201,201,201,201,201,201,73,73,73,73,73,73,73,73,
|
||||
185,185,185,185,185,185,185,185,57,57,57,57,57,57,57,57,
|
||||
249,249,249,249,249,249,249,249,121,121,121,121,121,121,121,121,
|
||||
153,153,153,153,153,153,153,153,25,25,25,25,25,25,25,25,
|
||||
217,217,217,217,217,217,217,217,89,89,89,89,89,89,89,89,
|
||||
161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
|
||||
33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
|
||||
225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
|
||||
97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
|
||||
129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
|
||||
65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
|
||||
177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
|
||||
49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
|
||||
241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
|
||||
113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
|
||||
145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
|
||||
17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
|
||||
209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
|
||||
81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
|
||||
173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,
|
||||
173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,
|
||||
45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,
|
||||
45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,
|
||||
237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,
|
||||
237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,
|
||||
109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
|
||||
109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
|
||||
141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,
|
||||
141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,
|
||||
13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
|
||||
13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
|
||||
205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,
|
||||
205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,
|
||||
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
|
||||
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
|
||||
189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,
|
||||
189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,
|
||||
61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,
|
||||
61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,
|
||||
253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
|
||||
253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
|
||||
125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,
|
||||
125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,
|
||||
157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,
|
||||
157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,
|
||||
29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,
|
||||
29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,
|
||||
221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,
|
||||
221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,
|
||||
93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,
|
||||
93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,
|
||||
165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
|
||||
165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
|
||||
165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
|
||||
165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
|
||||
37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
|
||||
37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
|
||||
37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
|
||||
37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
|
||||
229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
|
||||
229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
|
||||
229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
|
||||
229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
|
||||
101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
|
||||
101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
|
||||
101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
|
||||
101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
|
||||
133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
|
||||
133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
|
||||
133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
|
||||
133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
|
||||
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,
|
||||
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,
|
||||
197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
|
||||
197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
|
||||
197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
|
||||
197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
|
||||
69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
|
||||
69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
|
||||
69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
|
||||
69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
|
||||
181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
|
||||
181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
|
||||
181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
|
||||
181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
|
||||
53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
|
||||
53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
|
||||
53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
|
||||
53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
|
||||
245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
|
||||
245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
|
||||
245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
|
||||
245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
|
||||
117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
|
||||
117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
|
||||
117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
|
||||
117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
|
||||
149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
|
||||
149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
|
||||
149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
|
||||
149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
|
||||
21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
|
||||
21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
|
||||
21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
|
||||
21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
|
||||
213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
|
||||
213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
|
||||
213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
|
||||
213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
|
||||
85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85
|
||||
};
|
||||
@@ -1,237 +0,0 @@
|
||||
/*
|
||||
* Signed 16-bit audio data
|
||||
*
|
||||
* Source: answer.raw
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer and Linux Support Services
|
||||
*
|
||||
* Distributed under the terms of the GNU General Public License
|
||||
*
|
||||
*/
|
||||
|
||||
static signed short answer[] = {
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 0x19b7, 0x0245, 0xeee5, 0xb875, 0xd9a4, 0x6018, 0x660a, 0xc3c6,
|
||||
0x8741, 0xff55, 0x4c2e, 0x2146, 0xfed2, 0xf079, 0xcbd4, 0xe561, 0x3c41, 0x3166,
|
||||
0xd425, 0xdc59, 0x2748, 0x087d, 0xc72b, 0xfe3a, 0x4681, 0x14c6, 0xcf45, 0xdd38,
|
||||
0xf8dd, 0x0a39, 0x3a5a, 0x32b9, 0xbfec, 0x957f, 0x15a3, 0x70f4, 0x1d95, 0xbfc4,
|
||||
0xd367, 0xfda0, 0x0dc0, 0x29eb, 0x1fc2, 0xd684, 0xcab1, 0x19c7, 0x29ef, 0xe679,
|
||||
0xe9d0, 0x2b82, 0x151a, 0xca9f, 0xdb68, 0x1f4a, 0x271c, 0x0e2a, 0xfb32, 0xd1b2,
|
||||
0xc8ff, 0x2382, 0x6380, 0x0a52, 0xa118, 0xccbf, 0x2ddc, 0x33fd, 0x0964, 0xf2a4,
|
||||
0xdd81, 0xe092, 0x1a00, 0x325c, 0xf5e3, 0xd6a1, 0x0b6c, 0x1c75, 0xe4f8, 0xe07c,
|
||||
0x2082, 0x2b3e, 0xf445, 0xdaa9, 0xea13, 0xff3c, 0x245c, 0x35c1, 0xf308, 0xab53,
|
||||
0xdf59, 0x4698, 0x3f3b, 0xe7f7, 0xca84, 0xed4d, 0x0c3f, 0x1e94, 0x1c2d, 0xf06f,
|
||||
0xd4df, 0xff34, 0x23d8, 0x001e, 0xe3f1, 0x0b15, 0x2113, 0xf3fd, 0xd768, 0xf9a0,
|
||||
0x1d31, 0x1c6e, 0x0797, 0xe3a0, 0xce6c, 0xfd7b, 0x422a, 0x2c4c, 0xd364, 0xbf42,
|
||||
0x0278, 0x303e, 0x1c51, 0xf737, 0xe25a, 0xe75f, 0x0a8f, 0x22ab, 0x05f4, 0xe3f9,
|
||||
0xf8c4, 0x1705, 0x0162, 0xe49f, 0xfb8b, 0x1e2b, 0x13ac, 0xf044, 0xe07b, 0xf01a,
|
||||
0x1567, 0x2cbf, 0x0b75, 0xd01b, 0xd206, 0x1563, 0x38d7, 0x0f2e, 0xdb32, 0xdc30,
|
||||
0x023b, 0x1e44, 0x16eb, 0xf5f7, 0xe425, 0xfa33, 0x14d5, 0x0968, 0xeff2, 0xf762,
|
||||
0x1137, 0x0e59, 0xf13a, 0xe651, 0xff41, 0x1d60, 0x18fd, 0xf1e6, 0xd75f, 0xf097,
|
||||
0x20ec, 0x27fa, 0xfba4, 0xd5b8, 0xe68e, 0x1657, 0x2518, 0x04f6, 0xe5a3, 0xe976,
|
||||
0x0578, 0x18fa, 0x0a92, 0xec0a, 0xef2a, 0x111f, 0x12f4, 0xeec3, 0xe95e, 0x0d3a,
|
||||
0x18fd, 0xff72, 0xeefc, 0xf114, 0xfaaa, 0x14ee, 0x21db, 0xf56e, 0xcb49, 0xf621,
|
||||
0x3323, 0x1947, 0xe017, 0xe7e9, 0x0819, 0x0707, 0x084c, 0x0f57, 0xf152, 0xdf92,
|
||||
0x104a, 0x28eb, 0xedcc, 0xd4ad, 0x1415, 0x296d, 0xed9a, 0xdf57, 0x0cc2, 0x0d95,
|
||||
0xf7b5, 0x0deb, 0x0b34, 0xd713, 0xea08, 0x38d6, 0x216d, 0xc727, 0xdc32, 0x2cd2,
|
||||
0x1822, 0xe2d5, 0xfeb3, 0x106c, 0xe6e5, 0xf81e, 0x2fe8, 0x01af, 0xc180, 0x037a,
|
||||
0x42d8, 0xf88d, 0xc344, 0x0a4f, 0x2c4e, 0xf19d, 0xebeb, 0x162c, 0xf9e9, 0xde93,
|
||||
0x1b56, 0x2c60, 0xd8aa, 0xce3e, 0x2a41, 0x2eeb, 0xdab1, 0xde32, 0x1c32, 0x0aba,
|
||||
0xeabe, 0x1008, 0x136d, 0xda2f, 0xec3b, 0x31dd, 0x1130, 0xca79, 0xf5b8, 0x3423,
|
||||
0x0274, 0xd27d, 0x035e, 0x1e68, 0xf641, 0xf904, 0x1691, 0xef7d, 0xd57a, 0x1c3b,
|
||||
0x3c23, 0xe881, 0xc274, 0x0af5, 0x2962, 0xfa34, 0xf676, 0x0f71, 0xefcc, 0xe01f,
|
||||
0x19e7, 0x276f, 0xe694, 0xe134, 0x1c3a, 0x0e8b, 0xd8e7, 0xfa81, 0x2f8b, 0x07c5,
|
||||
0xd904, 0xf6fa, 0x0ca5, 0xf9a2, 0x0dc7, 0x2623, 0xec54, 0xbe23, 0x02b6, 0x4296,
|
||||
0x10cd, 0xda61, 0xf11c, 0x0103, 0xf41c, 0x10b4, 0x2a03, 0xf63c, 0xce1a, 0xfdbd,
|
||||
0x1fb4, 0xfc51, 0xf727, 0x1c8a, 0x04ff, 0xcf41, 0xec05, 0x2913, 0x1ce8, 0xf70c,
|
||||
0xf744, 0xede8, 0xdd77, 0x0d99, 0x43f1, 0x119c, 0xc14f, 0xd60e, 0x17cb, 0x1e19,
|
||||
0x0d4e, 0x0c95, 0xeed1, 0xcdf4, 0xf7a5, 0x331f, 0x1cd0, 0xeb17, 0xf082, 0xfb19,
|
||||
0xe899, 0xfdeb, 0x323c, 0x2036, 0xdad3, 0xd134, 0xfd03, 0x1345, 0x1c10, 0x2239,
|
||||
0xf656, 0xbc22, 0xdc3f, 0x3392, 0x3d59, 0xfd77, 0xdb4d, 0xe23f, 0xedbe, 0x0f7e,
|
||||
0x35cc, 0x1947, 0xd5dc, 0xd1bf, 0x035d, 0x16fc, 0x1174, 0x1675, 0x0249, 0xd2d4,
|
||||
0xd851, 0x184d, 0x32fe, 0x0f91, 0xee14, 0xe1e6, 0xdf9b, 0x016b, 0x3668, 0x2b2b,
|
||||
0xe20c, 0xc554, 0xf257, 0x1c05, 0x1fc5, 0x14f0, 0xf891, 0xd41c, 0xdf83, 0x1865,
|
||||
0x2de1, 0x0b16, 0xed58, 0xea0c, 0xea79, 0xfbd9, 0x22af, 0x2732, 0xf62f, 0xd389,
|
||||
0xe7d9, 0x0b39, 0x1cdc, 0x1de3, 0x038a, 0xd809, 0xd5f7, 0x0b55, 0x305e, 0x1910,
|
||||
0xf02e, 0xe089, 0xe7c7, 0x0195, 0x2265, 0x21da, 0xf743, 0xd8f2, 0xe978, 0x09a1,
|
||||
0x190a, 0x17c5, 0x045a, 0xe46d, 0xdd06, 0xffb2, 0x2293, 0x1cfe, 0xfd4d, 0xe4f9,
|
||||
0xe310, 0xfaf1, 0x1d22, 0x2376, 0x0113, 0xde3a, 0xe21b, 0x0204, 0x1ba1, 0x1bd6,
|
||||
0x0333, 0xe563, 0xe104, 0xfd51, 0x1bc1, 0x1ccf, 0x0285, 0xe757, 0xe35e, 0xfaf2,
|
||||
0x185d, 0x1d46, 0x06b7, 0xec13, 0xe108, 0xef6e, 0x121d, 0x2a17, 0x16a6, 0xe32c,
|
||||
0xc9a9, 0xf070, 0x2f48, 0x3788, 0xfa4e, 0xc32a, 0xd9c2, 0x1fa1, 0x36fe, 0x07fa,
|
||||
0xd9e4, 0xe577, 0x0e5e, 0x1755, 0xfb53, 0xed71, 0x0540, 0x19e0, 0x0301, 0xdc97,
|
||||
0xe391, 0x1937, 0x367c, 0x0bc9, 0xca4c, 0xc96b, 0x105d, 0x461f, 0x2416, 0xd481,
|
||||
0xbc97, 0xf8b7, 0x39af, 0x2ec9, 0xecc6, 0xcb50, 0xeee3, 0x1ffe, 0x1e8e, 0xf700,
|
||||
0xe66a, 0xff58, 0x149f, 0x02e5, 0xe792, 0xf2d8, 0x1a4d, 0x225a, 0xf642, 0xce7f,
|
||||
0xe6a6, 0x25e2, 0x38f5, 0x01d0, 0xc50f, 0xd243, 0x19bd, 0x3fc6, 0x14f0, 0xd2d7,
|
||||
0xcdb6, 0x069a, 0x2ffe, 0x1847, 0xe6f8, 0xdf0a, 0x0337, 0x1a90, 0x067a, 0xeb5b,
|
||||
0xf541, 0x143b, 0x14f2, 0xf092, 0xdc02, 0xfb91, 0x28a3, 0x2274, 0xeaa8, 0xc9e7,
|
||||
0xef48, 0x2d01, 0x322e, 0xf6d2, 0xc7cb, 0xe13b, 0x1fda, 0x3217, 0x0458, 0xd690,
|
||||
0xe2bf, 0x11c4, 0x21d5, 0x0291, 0xe5c8, 0xf3a9, 0x12ba, 0x11aa, 0xf22b, 0xe627,
|
||||
0x03ec, 0x219a, 0x1036, 0xe2f2, 0xd93f, 0x059c, 0x2ed6, 0x1b75, 0xe227, 0xce55,
|
||||
0xfb19, 0x2de0, 0x2477, 0xed08, 0xd148, 0xf307, 0x21d4, 0x2002, 0xf543, 0xdeac,
|
||||
0xf7f9, 0x18a9, 0x11d6, 0xf0ef, 0xe8e4, 0x05ea, 0x1ba5, 0x0727, 0xe448, 0xe748,
|
||||
0x100e, 0x265e, 0x07fc, 0xdbae, 0xde78, 0x0efa, 0x2ce0, 0x0f94, 0xddf1, 0xd9ea,
|
||||
0x0797, 0x28f6, 0x12eb, 0xe60c, 0xdf46, 0x0469, 0x1fbb, 0x0ced, 0xe9f6, 0xe95f,
|
||||
0x09fe, 0x1ab9, 0x02cb, 0xe5a4, 0xef2a, 0x1327, 0x1d7b, 0xfd07, 0xde3d, 0xed9c,
|
||||
0x17e5, 0x22e7, 0xfe3a, 0xdb38, 0xe9b9, 0x161a, 0x2416, 0x0175, 0xde3d, 0xe9de,
|
||||
0x1294, 0x1fc9, 0x00ea, 0xe2a7, 0xeee2, 0x1298, 0x1a7d, 0xfc1d, 0xe3bb, 0xf47a,
|
||||
0x1642, 0x185e, 0xf727, 0xe1af, 0xf709, 0x19c3, 0x18e7, 0xf50d, 0xe010, 0xf75b,
|
||||
0x1a9c, 0x18d8, 0xf4c5, 0xe0c9, 0xf865, 0x1a1c, 0x16d5, 0xf3a6, 0xe257, 0xfaf2,
|
||||
0x1a44, 0x14d5, 0xf34f, 0xe4b6, 0xfc77, 0x17d5, 0x0ff8, 0xf133, 0xe8b7, 0x0344,
|
||||
0x1a37, 0x0ad5, 0xe95e, 0xe61a, 0x08a5, 0x227e, 0x0e33, 0xe4a7, 0xdd70, 0x03b0,
|
||||
0x25f4, 0x17b2, 0xec0a, 0xdb4e, 0xf898, 0x1ba3, 0x18f6, 0xf973, 0xe87f, 0xf77a,
|
||||
0x0b93, 0x096c, 0xfb0e, 0xfb03, 0x0896, 0x0940, 0xf51d, 0xe904, 0xfdc7, 0x1dda,
|
||||
0x1bf9, 0xf29b, 0xd37f, 0xea1b, 0x1f37, 0x3175, 0x07eb, 0xd3f7, 0xd46b, 0x077d,
|
||||
0x2eeb, 0x1e67, 0xeeae, 0xd8c7, 0xef85, 0x1119, 0x18d3, 0x088e, 0xf953, 0xf5ad,
|
||||
0xf556, 0xf63d, 0x0234, 0x167a, 0x19a1, 0xfbf9, 0xd873, 0xdd4b, 0x0f06, 0x3748,
|
||||
0x21e6, 0xe181, 0xc032, 0xe79a, 0x2bec, 0x3e76, 0x0b1b, 0xce41, 0xcb23, 0xff96,
|
||||
0x2d79, 0x26d1, 0xfcc7, 0xdf8a, 0xe525, 0xfd83, 0x10f1, 0x16d7, 0x0f50, 0xfaea,
|
||||
0xe3f1, 0xe20f, 0x0158, 0x27d9, 0x2866, 0xf96f, 0xcb34, 0xd563, 0x11d6, 0x3d25,
|
||||
0x2424, 0xe254, 0xc2c9, 0xe7cd, 0x248d, 0x34f5, 0x0c42, 0xdcd0, 0xd827, 0xfa65,
|
||||
0x19eb, 0x1b50, 0x0721, 0xf396, 0xeb9c, 0xefde, 0x0016, 0x1594, 0x1cc1, 0x0658,
|
||||
0xe22b, 0xd852, 0xfb3e, 0x2923, 0x2c78, 0xfc87, 0xcdb5, 0xd69c, 0x0e3c, 0x3527,
|
||||
0x201f, 0xe993, 0xcf9e, 0xeb21, 0x183f, 0x25ea, 0x0c93, 0xed4d, 0xe5f9, 0xf548,
|
||||
0x07fb, 0x117c, 0x0ff2, 0x0398, 0xf08c, 0xe628, 0xf489, 0x143b, 0x2419, 0x0ccf,
|
||||
0xe2cc, 0xd5a6, 0xf861, 0x2615, 0x2a1b, 0xfeb4, 0xd543, 0xdc53, 0x09b4, 0x2901,
|
||||
0x19ff, 0xf24a, 0xde86, 0xeec4, 0x0b7b, 0x1733, 0x0d0a, 0xfc24, 0xf1bb, 0xf110,
|
||||
0xfa03, 0x0a0f, 0x15d4, 0x0e21, 0xf435, 0xe17e, 0xee90, 0x1225, 0x2527, 0x0efa,
|
||||
0xe61f, 0xd916, 0xf7b8, 0x1f50, 0x2326, 0x0099, 0xe01e, 0xe473, 0x0491, 0x1b37,
|
||||
0x1360, 0xfb17, 0xecd9, 0xf20d, 0x0051, 0x0aec, 0x0d4a, 0x073d, 0xfa5a, 0xeeb8,
|
||||
0xf165, 0x0516, 0x17dc, 0x12da, 0xf71b, 0xe213, 0xed85, 0x0eef, 0x20c8, 0x0e09,
|
||||
0xebcc, 0xe0d4, 0xf848, 0x1637, 0x19d6, 0x026b, 0xec09, 0xed00, 0xff9b, 0x0e5a,
|
||||
0x0d6b, 0x026c, 0xf865, 0xf4da, 0xf888, 0x025a, 0x0cbb, 0x0d53, 0xff96, 0xeefa,
|
||||
0xee80, 0x021c, 0x15d6, 0x126a, 0xf9c1, 0xe724, 0xf017, 0x0aa1, 0x18b6, 0x0b4e,
|
||||
0xf2d7, 0xea91, 0xf957, 0x0cac, 0x1061, 0x03f4, 0xf6ad, 0xf476, 0xfbdf, 0x0489,
|
||||
0x08b1, 0x06df, 0xffcf, 0xf766, 0xf537, 0xfddf, 0x0ad4, 0x0e15, 0x01da, 0xf205,
|
||||
0xf0a0, 0x0082, 0x1066, 0x0e41, 0xfc71, 0xef1b, 0xf4ad, 0x05cd, 0x0f32, 0x07ed,
|
||||
0xf9c8, 0xf401, 0xfa93, 0x04af, 0x088c, 0x04a7, 0xfe15, 0xf9f1, 0xfa64, 0xff1e,
|
||||
0x0539, 0x078c, 0x02af, 0xfa1a, 0xf69d, 0xfd09, 0x075b, 0x0a3d, 0x01f2, 0xf761,
|
||||
0xf642, 0xffa7, 0x08f3, 0x0830, 0xff05, 0xf7db, 0xf9bc, 0x0174, 0x068b, 0x04b2,
|
||||
0xfeff, 0xfb39, 0xfc1a, 000000, 0x0371, 0x03d7, 0x00fe, 0xfd37, 0xfbe0, 0xfe78,
|
||||
0x02af, 0x044a, 0x0180, 0xfd43, 0xfc00, 0xfed1, 0x02aa, 0x0346, 0x00dd, 0xfde0,
|
||||
0xfbfe, 0x0114, 0x0987, 0x04bc, 0xf49d, 0xf23a, 0x06ab, 0x162e, 0x0544, 0xe76b,
|
||||
0xea25, 0x1015, 0x2474, 0x0431, 0xd7d3, 0xe1ec, 0x1923, 0x2df5, 0x01cd, 0xd386,
|
||||
0xe3d9, 0x1b9d, 0x2c62, 0xfeb8, 0xd31a, 0xe6ba, 0x1dbd, 0x2abb, 0xfbab, 0xd2ed,
|
||||
0xe9ab, 0x1fa7, 0x28ef, 0xf8b3, 0xd2f5, 0xeca5, 0x2160, 0x26fd, 0xf5d7, 0xd334,
|
||||
0xefa1, 0x22e5, 0x24ea, 0xf31b, 0xd3a9, 0xf29f, 0x2435, 0x22b6, 0xf07e, 0xd44e,
|
||||
0xf59b, 0x2551, 0x2067, 0xee08, 0xd527, 0xf88e, 0x2639, 0x1e00, 0xebb6, 0xd62d,
|
||||
0xfb77, 0x26eb, 0x1b85, 0xe98b, 0xd75f, 0xfe51, 0x276b, 0x18f9, 0xe78e, 0xd8b9,
|
||||
0x011a, 0x27b6, 0x1660, 0xe5bb, 0xda3a, 0x03cc, 0x27cf, 0x13bd, 0xe415, 0xdbdf,
|
||||
0x066a, 0x27b7, 0x1117, 0xe29e, 0xdda5, 0x08ec, 0x276e, 0x0e6d, 0xe154, 0xdf89,
|
||||
0x0b52, 0x26f6, 0x0bc7, 0xe039, 0xe185, 0x0d96, 0x2653, 0x0924, 0xdf4e, 0xe399,
|
||||
0x0fb9, 0x2584, 0x068b, 0xde93, 0xe5c0, 0x11b8, 0x248e, 0x03fd, 0xde08, 0xe7f8,
|
||||
0x1390, 0x2372, 0x0180, 0xddaa, 0xea3c, 0x1544, 0x2231, 0xff12, 0xdd7a, 0xec89,
|
||||
0x16cf, 0x20d0, 0xfcb9, 0xdd77, 0xeedb, 0x1831, 0x1f52, 0xfa77, 0xdd9f, 0xf132,
|
||||
0x1969, 0x1db7, 0xf850, 0xddf1, 0xf385, 0x1a75, 0x1c06, 0xf645, 0xde6b, 0xf5d7,
|
||||
0x1b5b, 0x1a3f, 0xf457, 0xdf0d, 0xf820, 0x1c13, 0x1867, 0xf288, 0xdfd2, 0xfa5f,
|
||||
0x1ca1, 0x167f, 0xf0db, 0xe0ba, 0xfc92, 0x1d06, 0x148b, 0xef50, 0xe1c1, 0xfeb5,
|
||||
0x1d43, 0x1290, 0xede9, 0xe2e6, 0x00c6, 0x1d58, 0x108e, 0xeca7, 0xe426, 0x02c4,
|
||||
0x1d45, 0x0e8a, 0xeb8a, 0xe57f, 0x04a9, 0x1d0e, 0x0c87, 0xea92, 0xe6ec, 0x0677,
|
||||
0x1cb2, 0x0a87, 0xe9be, 0xe86e, 0x082a, 0x1c34, 0x088b, 0xe912, 0xe9fe, 0x09c1,
|
||||
0x1b95, 0x069c, 0xe88c, 0xeb9c, 0x0b3a, 0x1ad9, 0x04b6, 0xe82a, 0xed43, 0x0c96,
|
||||
0x1a00, 0x02df, 0xe7eb, 0xeef3, 0x0dd0, 0x190d, 0x0116, 0xe7d0, 0xf0a8, 0x0eec,
|
||||
0x1804, 0xff61, 0xe7d8, 0xf25d, 0x0fe6, 0x16e3, 0xfdc0, 0xe800, 0xf412, 0x10bf,
|
||||
0x15b1, 0xfc36, 0xe848, 0xf5c5, 0x1176, 0x146e, 0xfac2, 0xe8ad, 0xf771, 0x120d,
|
||||
0x1320, 0xf969, 0xe92e, 0xf913, 0x1282, 0x11c4, 0xf828, 0xe9cb, 0xfaac, 0x12d8,
|
||||
0x1062, 0xf703, 0xea7e, 0xfc38, 0x130e, 0x0efa, 0xf5fb, 0xeb49, 0xfdb5, 0x1325,
|
||||
0x0d8e, 0xf50e, 0xec26, 0xff20, 0x131e, 0x0c21, 0xf43f, 0xed15, 0x007a, 0x12fa,
|
||||
0x0ab6, 0xf38d, 0xee15, 0x01be, 0x12bd, 0x094f, 0xf2f9, 0xef22, 0x02ef, 0x1265,
|
||||
0x07f0, 0xf283, 0xf037, 0x0408, 0x11f6, 0x0699, 0xf226, 0xf156, 0x050a, 0x1170,
|
||||
0x054b, 0xf1e8, 0xf27a, 0x05f4, 0x10d8, 0x040c, 0xf1c5, 0xf3a3, 0x06c2, 0x102c,
|
||||
0x02da, 0xf1bc, 0xf4cc, 0x0779, 0x0f71, 0x01b7, 0xf1cc, 0xf5f5, 0x0815, 0x0ea7,
|
||||
0x00a8, 0xf1f4, 0xf719, 0x0899, 0x0dd2, 0xffab, 0xf233, 0xf839, 0x0902, 0x0cf4,
|
||||
0xfec0, 0xf288, 0xf950, 0x0952, 0x0c0e, 0xfdec, 0xf2ee, 0xfa5d, 0x0989, 0x0b23,
|
||||
0xfd2d, 0xf368, 0xfb62, 0x09a7, 0x0a35, 0xfc85, 0xf3f1, 0xfc58, 0x09af, 0x0946,
|
||||
0xfbf2, 0xf488, 0xfd3f, 0x09a1, 0x0859, 0xfb77, 0xf52c, 0xfe17, 0x097d, 0x076f,
|
||||
0xfb14, 0xf5d8, 0xfede, 0x0945, 0x068a, 0xfac6, 0xf68d, 0xff93, 0x08fb, 0x05ad,
|
||||
0xfa8e, 0xf747, 0x0034, 0x08a1, 0x04da, 0xfa6f, 0xf805, 0x00c2, 0x0836, 0x0410,
|
||||
0xfa63, 0xf8c6, 0x013c, 0x07bf, 0x0354, 0xfa6c, 0xf985, 0x01a1, 0x073b, 0x02a4,
|
||||
0xfa8a, 0xfa43, 0x01f1, 0x06af, 0x0204, 0xfab9, 0xfafc, 0x022c, 0x0619, 0x0175,
|
||||
0xfafa, 0xfbae, 0x0252, 0x057f, 0x00f6, 0xfb4b, 0xfc5a, 0x0263, 0x04e0, 0x008b,
|
||||
0xfbaa, 0xfcfa, 0x0262, 0x0440, 0x0032, 0xfc16, 0xfd90, 0x024b, 0x03a0, 0xffec,
|
||||
0xfc8c, 0xfe19, 0x0225, 0x0301, 0xffb9, 0xfd0c, 0xfe93, 0x01ea, 0x0267, 0xff9c,
|
||||
0xfd95, 0xfefe, 0x01a0, 0x01d3, 0xff90, 0xfe22, 0xff5a, 0x0147, 0x0145, 0xff99,
|
||||
0xfeb3, 0xffa1, 0x00e0, 0x00c3, 0xffb6, 0xff46, 0xffd9, 0x006d, 0x004b, 0xffe5,
|
||||
0xffda, 0xfffc, 000000, 0xfffe, 000000, 0xffff, 000000, 0xffff, 0xffff, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000 };
|
||||
3238
channels/chan_iax.c
3238
channels/chan_iax.c
File diff suppressed because it is too large
Load Diff
@@ -53,10 +53,7 @@ static char context[AST_MAX_EXTENSION]= "default";
|
||||
static char language[MAX_LANGUAGE] = "";
|
||||
|
||||
/* Initialization String */
|
||||
static char initstr[AST_MAX_INIT_STR] = "ATE0Q0";
|
||||
|
||||
/* Default MSN */
|
||||
static char msn[AST_MAX_EXTENSION]="";
|
||||
static char initstr[AST_MAX_INIT_STR] = "ATE1Q0";
|
||||
|
||||
static int usecnt =0;
|
||||
|
||||
@@ -161,10 +158,9 @@ int ast_unregister_modem_driver(struct ast_modem_driver *mc)
|
||||
|
||||
static int modem_call(struct ast_channel *ast, char *idest, int timeout)
|
||||
{
|
||||
static int modem_hangup(struct ast_channel *ast);
|
||||
struct ast_modem_pvt *p;
|
||||
int ms = timeout;
|
||||
char rdest[80], *where, dstr[100];
|
||||
char rdest[80], *where;
|
||||
strncpy(rdest, idest, sizeof(rdest));
|
||||
strtok(rdest, ":");
|
||||
where = strtok(NULL, ":");
|
||||
@@ -173,17 +169,9 @@ static int modem_call(struct ast_channel *ast, char *idest, int timeout)
|
||||
return -1;
|
||||
}
|
||||
p = ast->pvt->pvt;
|
||||
strcpy(dstr,where + p->stripmsd);
|
||||
/* if not a transfer or just sending tones, must be in correct state */
|
||||
if (strcasecmp(rdest, "transfer") && strcasecmp(rdest,"sendtones")) {
|
||||
if ((ast->state != AST_STATE_DOWN) && (ast->state != AST_STATE_RESERVED)) {
|
||||
ast_log(LOG_WARNING, "modem_call called on %s, neither down nor reserved\n", ast->name);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (!strcasecmp(rdest,"transfer")) /* if a transfer, put in transfer stuff */
|
||||
{
|
||||
sprintf(dstr,"!,%s",where + p->stripmsd);
|
||||
if ((ast->state != AST_STATE_DOWN) && (ast->state != AST_STATE_RESERVED)) {
|
||||
ast_log(LOG_WARNING, "modem_call called on %s, neither down nor reserved\n", ast->name);
|
||||
return -1;
|
||||
}
|
||||
if (!strcasecmp(where, "handset")) {
|
||||
if (p->mc->setdev)
|
||||
@@ -196,7 +184,7 @@ static int modem_call(struct ast_channel *ast, char *idest, int timeout)
|
||||
if (p->mc->setdev(p, MODEM_DEV_TELCO_SPK))
|
||||
return -1;
|
||||
if (p->mc->dial)
|
||||
p->mc->dial(p, dstr);
|
||||
p->mc->dial(p, where + p->stripmsd);
|
||||
ast->state = AST_STATE_DIALING;
|
||||
while((ast->state != AST_STATE_UP) && (ms > 0)) {
|
||||
ms = ast_waitfor(ast, ms);
|
||||
@@ -214,20 +202,14 @@ static int modem_call(struct ast_channel *ast, char *idest, int timeout)
|
||||
|
||||
int ast_modem_send(struct ast_modem_pvt *p, char *cmd, int len)
|
||||
{
|
||||
int i;
|
||||
usleep(5000);
|
||||
int res;
|
||||
if (!len) {
|
||||
for(i = 0; cmd[i];)
|
||||
{
|
||||
if (fwrite(cmd + i,1,1,p->f) != 1)
|
||||
{
|
||||
if (errno == EWOULDBLOCK) continue;
|
||||
return -1;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
tcdrain(fileno(p->f));
|
||||
fprintf(p->f,"\r\n");
|
||||
fprintf(p->f, "%s\r\n", cmd);
|
||||
res = ast_modem_expect(p, cmd, ECHO_TIMEOUT);
|
||||
if (res) {
|
||||
ast_log(LOG_WARNING, "Unexpected reply %s\n", p->response);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
if (fwrite(cmd, 1, len, p->f) < len)
|
||||
@@ -238,50 +220,18 @@ int ast_modem_send(struct ast_modem_pvt *p, char *cmd, int len)
|
||||
|
||||
int ast_modem_read_response(struct ast_modem_pvt *p, int timeout)
|
||||
{
|
||||
int res = -1,c,i;
|
||||
int res = -1;
|
||||
timeout *= 1000;
|
||||
p->response[0] = 0;
|
||||
c = i = 0;
|
||||
strncpy(p->response, "(No Response)", sizeof(p->response));
|
||||
do {
|
||||
res = ast_waitfor_n_fd(&p->fd, 1, &timeout, NULL);
|
||||
res = ast_waitfor_n_fd(&p->fd, 1, &timeout);
|
||||
if (res < 0) {
|
||||
strncpy(p->response, "(No Response)", sizeof(p->response));
|
||||
return -1;
|
||||
}
|
||||
/* get no more then buffer length */
|
||||
while(i < sizeof(p->response) - 1)
|
||||
{
|
||||
c = fgetc(p->f); /* get a char */
|
||||
if (c < 1) /* if error */
|
||||
{
|
||||
/* if nothing in buffer, go back into timeout stuff */
|
||||
if (errno == EWOULDBLOCK) break;
|
||||
/* return as error */
|
||||
strncpy(p->response, "(No Response)", sizeof(p->response));
|
||||
return -1;
|
||||
}
|
||||
/* save char */
|
||||
p->response[i++] = c;
|
||||
p->response[i] = 0;
|
||||
/* if end of input */
|
||||
if (c == '\n') break;
|
||||
}
|
||||
if (c >= 0) /* if input terminated normally */
|
||||
{
|
||||
/* ignore just CR/LF */
|
||||
if (!strcmp(p->response,"\r\n"))
|
||||
{
|
||||
/* reset input buffer stuff */
|
||||
i = 0;
|
||||
p->response[0] = 0;
|
||||
}
|
||||
else /* otherwise return with info in buffer */
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* Read a response */
|
||||
fgets(p->response, sizeof(p->response), p->f);
|
||||
return 0;
|
||||
} while(timeout > 0);
|
||||
strncpy(p->response, "(No Response)", sizeof(p->response));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -291,13 +241,13 @@ int ast_modem_expect(struct ast_modem_pvt *p, char *result, int timeout)
|
||||
timeout *= 1000;
|
||||
strncpy(p->response, "(No Response)", sizeof(p->response));
|
||||
do {
|
||||
res = ast_waitfor_n_fd(&p->fd, 1, &timeout, NULL);
|
||||
res = ast_waitfor_n_fd(&p->fd, 1, &timeout);
|
||||
if (res < 0) {
|
||||
return -1;
|
||||
}
|
||||
/* Read a response */
|
||||
fgets(p->response, sizeof(p->response), p->f);
|
||||
#if 0
|
||||
#if 0
|
||||
fprintf(stderr, "Modem said: %s", p->response);
|
||||
#endif
|
||||
if (!strncasecmp(p->response, result, strlen(result)))
|
||||
@@ -320,12 +270,11 @@ void ast_modem_trim(char *s)
|
||||
|
||||
static int modem_setup(struct ast_modem_pvt *p, int baudrate)
|
||||
{
|
||||
|
||||
/* Make sure there's a modem there and that it's in a reasonable
|
||||
mode. Set the baud rate, etc. */
|
||||
char identity[256];
|
||||
char *ident = NULL;
|
||||
char etx[2] = { 0x10, '!' };
|
||||
char etx[2] = { 0x10, 0x03 };
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "Setting up modem %s\n", p->dev);
|
||||
if (ast_modem_send(p, etx, 2)) {
|
||||
@@ -336,7 +285,6 @@ static int modem_setup(struct ast_modem_pvt *p, int baudrate)
|
||||
ast_log(LOG_WARNING, "Failed to send enter?\n");
|
||||
return -1;
|
||||
}
|
||||
usleep(10000);
|
||||
/* Read any outstanding stuff */
|
||||
while(!ast_modem_read_response(p, 0));
|
||||
if (ast_modem_send(p, "ATZ", 0)) {
|
||||
@@ -400,8 +348,7 @@ static int modem_setup(struct ast_modem_pvt *p, int baudrate)
|
||||
static int modem_hangup(struct ast_channel *ast)
|
||||
{
|
||||
struct ast_modem_pvt *p;
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "modem_hangup(%s)\n", ast->name);
|
||||
ast_log(LOG_DEBUG, "modem_hangup(%s)\n", ast->name);
|
||||
p = ast->pvt->pvt;
|
||||
/* Hang up */
|
||||
if (p->mc->hangup)
|
||||
@@ -412,11 +359,11 @@ static int modem_hangup(struct ast_channel *ast)
|
||||
ast->state = AST_STATE_DOWN;
|
||||
memset(p->cid, 0, sizeof(p->cid));
|
||||
((struct ast_modem_pvt *)(ast->pvt->pvt))->owner = NULL;
|
||||
ast_pthread_mutex_lock(&usecnt_lock);
|
||||
pthread_mutex_lock(&usecnt_lock);
|
||||
usecnt--;
|
||||
if (usecnt < 0)
|
||||
ast_log(LOG_WARNING, "Usecnt < 0???\n");
|
||||
ast_pthread_mutex_unlock(&usecnt_lock);
|
||||
pthread_mutex_unlock(&usecnt_lock);
|
||||
ast_update_use_count();
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
|
||||
@@ -430,8 +377,7 @@ static int modem_answer(struct ast_channel *ast)
|
||||
{
|
||||
struct ast_modem_pvt *p;
|
||||
int res=0;
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "modem_answer(%s)\n", ast->name);
|
||||
ast_log(LOG_DEBUG, "modem_hangup(%s)\n", ast->name);
|
||||
p = ast->pvt->pvt;
|
||||
if (p->mc->answer) {
|
||||
res = p->mc->answer(p);
|
||||
@@ -443,7 +389,6 @@ static int modem_answer(struct ast_channel *ast)
|
||||
return res;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static char modem_2digit(char c)
|
||||
{
|
||||
if (c == 12)
|
||||
@@ -455,7 +400,7 @@ static char modem_2digit(char c)
|
||||
else
|
||||
return '?';
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct ast_frame *modem_read(struct ast_channel *ast)
|
||||
{
|
||||
struct ast_modem_pvt *p = ast->pvt->pvt;
|
||||
@@ -481,8 +426,8 @@ struct ast_channel *ast_modem_new(struct ast_modem_pvt *i, int state)
|
||||
if (tmp) {
|
||||
snprintf(tmp->name, sizeof(tmp->name), "Modem[%s]/%s", i->mc->name, i->dev + 5);
|
||||
tmp->type = type;
|
||||
tmp->fds[0] = i->fd;
|
||||
tmp->nativeformats = i->mc->formats;
|
||||
tmp->fd = i->fd;
|
||||
tmp->format = i->mc->formats;
|
||||
tmp->state = state;
|
||||
if (state == AST_STATE_RING)
|
||||
tmp->rings = 1;
|
||||
@@ -499,9 +444,9 @@ struct ast_channel *ast_modem_new(struct ast_modem_pvt *i, int state)
|
||||
if (strlen(i->language))
|
||||
strncpy(tmp->language,i->language, sizeof(tmp->language));
|
||||
i->owner = tmp;
|
||||
ast_pthread_mutex_lock(&usecnt_lock);
|
||||
pthread_mutex_lock(&usecnt_lock);
|
||||
usecnt++;
|
||||
ast_pthread_mutex_unlock(&usecnt_lock);
|
||||
pthread_mutex_unlock(&usecnt_lock);
|
||||
ast_update_use_count();
|
||||
if (state != AST_STATE_DOWN) {
|
||||
if (ast_pbx_start(tmp)) {
|
||||
@@ -519,10 +464,10 @@ static void modem_mini_packet(struct ast_modem_pvt *i)
|
||||
{
|
||||
struct ast_frame *fr;
|
||||
fr = i->mc->read(i);
|
||||
if (!fr) return;
|
||||
if (fr->frametype == AST_FRAME_CONTROL) {
|
||||
if (fr->subclass == AST_CONTROL_RING) {
|
||||
ast_modem_new(i, AST_STATE_RING);
|
||||
restart_monitor();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -544,14 +489,14 @@ static void *do_monitor(void *data)
|
||||
for(;;) {
|
||||
/* Don't let anybody kill us right away. Nobody should lock the interface list
|
||||
and wait for the monitor list, but the other way around is okay. */
|
||||
if (ast_pthread_mutex_lock(&monlock)) {
|
||||
if (pthread_mutex_lock(&monlock)) {
|
||||
ast_log(LOG_ERROR, "Unable to grab monitor lock\n");
|
||||
return NULL;
|
||||
}
|
||||
/* Lock the interface list */
|
||||
if (ast_pthread_mutex_lock(&iflock)) {
|
||||
if (pthread_mutex_lock(&iflock)) {
|
||||
ast_log(LOG_ERROR, "Unable to grab interface lock\n");
|
||||
ast_pthread_mutex_unlock(&monlock);
|
||||
pthread_mutex_unlock(&monlock);
|
||||
return NULL;
|
||||
}
|
||||
/* Build the stuff we're going to select on, that is the socket of every
|
||||
@@ -574,10 +519,10 @@ static void *do_monitor(void *data)
|
||||
i = i->next;
|
||||
}
|
||||
/* Okay, now that we know what to do, release the interface lock */
|
||||
ast_pthread_mutex_unlock(&iflock);
|
||||
pthread_mutex_unlock(&iflock);
|
||||
|
||||
/* And from now on, we're okay to be killed, so release the monitor lock as well */
|
||||
ast_pthread_mutex_unlock(&monlock);
|
||||
pthread_mutex_unlock(&monlock);
|
||||
#if 0
|
||||
ast_log(LOG_DEBUG, "In monitor, n=%d, pid=%d\n", n, getpid());
|
||||
#endif
|
||||
@@ -592,7 +537,7 @@ static void *do_monitor(void *data)
|
||||
}
|
||||
/* Alright, lock the interface list again, and let's look and see what has
|
||||
happened */
|
||||
if (ast_pthread_mutex_lock(&iflock)) {
|
||||
if (pthread_mutex_lock(&iflock)) {
|
||||
ast_log(LOG_WARNING, "Unable to lock the interface list\n");
|
||||
continue;
|
||||
}
|
||||
@@ -608,7 +553,7 @@ static void *do_monitor(void *data)
|
||||
}
|
||||
i=i->next;
|
||||
}
|
||||
ast_pthread_mutex_unlock(&iflock);
|
||||
pthread_mutex_unlock(&iflock);
|
||||
}
|
||||
/* Never reached */
|
||||
return NULL;
|
||||
@@ -620,12 +565,12 @@ static int restart_monitor()
|
||||
/* If we're supposed to be stopped -- stay stopped */
|
||||
if (monitor_thread == -2)
|
||||
return 0;
|
||||
if (ast_pthread_mutex_lock(&monlock)) {
|
||||
if (pthread_mutex_lock(&monlock)) {
|
||||
ast_log(LOG_WARNING, "Unable to lock monitor\n");
|
||||
return -1;
|
||||
}
|
||||
if (monitor_thread == pthread_self()) {
|
||||
ast_pthread_mutex_unlock(&monlock);
|
||||
pthread_mutex_unlock(&monlock);
|
||||
ast_log(LOG_WARNING, "Cannot kill myself\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -637,29 +582,14 @@ static int restart_monitor()
|
||||
}
|
||||
/* Start a new monitor */
|
||||
if (pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) {
|
||||
ast_pthread_mutex_unlock(&monlock);
|
||||
pthread_mutex_unlock(&monlock);
|
||||
ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
|
||||
return -1;
|
||||
}
|
||||
ast_pthread_mutex_unlock(&monlock);
|
||||
pthread_mutex_unlock(&monlock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void stty(struct ast_modem_pvt *p)
|
||||
{
|
||||
struct termios mode;
|
||||
memset(&mode, 0, sizeof(mode));
|
||||
if (tcgetattr(p->fd, &mode)) {
|
||||
ast_log(LOG_WARNING, "Unable to get serial parameters on %s: %s\n", p->dev, strerror(errno));
|
||||
return;
|
||||
}
|
||||
cfmakeraw(&mode);
|
||||
cfsetspeed(&mode, B115200);
|
||||
if (tcsetattr(p->fd, TCSANOW, &mode))
|
||||
ast_log(LOG_WARNING, "Unable to set serial parameters on %s: %s\n", p->dev, strerror(errno));
|
||||
|
||||
}
|
||||
|
||||
static struct ast_modem_pvt *mkif(char *iface)
|
||||
{
|
||||
/* Make a ast_modem_pvt structure for this interface */
|
||||
@@ -669,7 +599,6 @@ static struct ast_modem_pvt *mkif(char *iface)
|
||||
#endif
|
||||
|
||||
tmp = malloc(sizeof(struct ast_modem_pvt));
|
||||
memset(tmp, 0, sizeof(struct ast_modem_pvt));
|
||||
if (tmp) {
|
||||
tmp->fd = open(iface, O_RDWR | O_NONBLOCK);
|
||||
if (tmp->fd < 0) {
|
||||
@@ -678,11 +607,6 @@ static struct ast_modem_pvt *mkif(char *iface)
|
||||
return NULL;
|
||||
}
|
||||
strncpy(tmp->language, language, sizeof(tmp->language));
|
||||
strncpy(tmp->msn, msn, sizeof(tmp->msn));
|
||||
strncpy(tmp->dev, iface, sizeof(tmp->dev));
|
||||
/* Maybe in the future we want to allow variable
|
||||
serial settings */
|
||||
stty(tmp);
|
||||
tmp->f = fdopen(tmp->fd, "w+");
|
||||
/* Disable buffering */
|
||||
setvbuf(tmp->f, NULL, _IONBF,0);
|
||||
@@ -701,6 +625,7 @@ static struct ast_modem_pvt *mkif(char *iface)
|
||||
tmp->dialtype = dialtype;
|
||||
tmp->mode = gmode;
|
||||
memset(tmp->cid, 0, sizeof(tmp->cid));
|
||||
strncpy(tmp->dev, iface, sizeof(tmp->dev));
|
||||
strncpy(tmp->context, context, sizeof(tmp->context));
|
||||
strncpy(tmp->initstr, initstr, sizeof(tmp->initstr));
|
||||
tmp->next = NULL;
|
||||
@@ -725,7 +650,7 @@ static struct ast_channel *modem_request(char *type, int format, void *data)
|
||||
strtok(dev, ":");
|
||||
oldformat = format;
|
||||
/* Search for an unowned channel */
|
||||
if (ast_pthread_mutex_lock(&iflock)) {
|
||||
if (pthread_mutex_lock(&iflock)) {
|
||||
ast_log(LOG_ERROR, "Unable to lock interface list???\n");
|
||||
return NULL;
|
||||
}
|
||||
@@ -748,7 +673,7 @@ static struct ast_channel *modem_request(char *type, int format, void *data)
|
||||
if (!p)
|
||||
ast_log(LOG_WARNING, "Requested device '%s' does not exist\n", p->dev);
|
||||
|
||||
ast_pthread_mutex_unlock(&iflock);
|
||||
pthread_mutex_unlock(&iflock);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@@ -765,7 +690,7 @@ int load_module()
|
||||
ast_log(LOG_ERROR, "Unable to load config %s\n", config);
|
||||
return -1;
|
||||
}
|
||||
if (ast_pthread_mutex_lock(&iflock)) {
|
||||
if (pthread_mutex_lock(&iflock)) {
|
||||
/* It's a little silly to lock it, but we mind as well just to be sure */
|
||||
ast_log(LOG_ERROR, "Unable to lock interface list???\n");
|
||||
return -1;
|
||||
@@ -782,9 +707,9 @@ int load_module()
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Unable to register channel '%s'\n", v->value);
|
||||
ast_destroy(cfg);
|
||||
ast_pthread_mutex_unlock(&iflock);
|
||||
pthread_mutex_unlock(&iflock);
|
||||
unload_module();
|
||||
ast_pthread_mutex_unlock(&iflock);
|
||||
pthread_mutex_unlock(&iflock);
|
||||
return -1;
|
||||
}
|
||||
} else if (!strcasecmp(v->name, "driver")) {
|
||||
@@ -795,7 +720,7 @@ int load_module()
|
||||
if (ast_load_resource(driver)) {
|
||||
ast_log(LOG_ERROR, "Failed to load driver %s\n", driver);
|
||||
ast_destroy(cfg);
|
||||
ast_pthread_mutex_unlock(&iflock);
|
||||
pthread_mutex_unlock(&iflock);
|
||||
unload_module();
|
||||
return -1;
|
||||
}
|
||||
@@ -818,16 +743,13 @@ int load_module()
|
||||
dialtype = toupper(v->value[0]);
|
||||
} else if (!strcasecmp(v->name, "context")) {
|
||||
strncpy(context, v->value, sizeof(context));
|
||||
} else if (!strcasecmp(v->name, "msn")) {
|
||||
strncpy(msn, v->value, sizeof(msn));
|
||||
} else if (!strcasecmp(v->name, "language")) {
|
||||
strncpy(language, v->value, sizeof(language));
|
||||
}
|
||||
v = v->next;
|
||||
}
|
||||
ast_pthread_mutex_unlock(&iflock);
|
||||
if (ast_channel_register(type, tdesc, /* XXX Don't know our types -- maybe we should register more than one XXX */
|
||||
AST_FORMAT_SLINEAR, modem_request)) {
|
||||
pthread_mutex_unlock(&iflock);
|
||||
if (ast_channel_register(type, tdesc, /* XXX Don't know our types -- maybe we should register more than one XXX */ AST_FORMAT_SLINEAR, modem_request)) {
|
||||
ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
|
||||
ast_destroy(cfg);
|
||||
unload_module();
|
||||
@@ -844,7 +766,7 @@ int unload_module()
|
||||
struct ast_modem_pvt *p, *pl;
|
||||
/* First, take us out of the channel loop */
|
||||
ast_channel_unregister(type);
|
||||
if (!ast_pthread_mutex_lock(&iflock)) {
|
||||
if (!pthread_mutex_lock(&iflock)) {
|
||||
/* Hangup all interfaces if they have an owner */
|
||||
p = iflist;
|
||||
while(p) {
|
||||
@@ -853,24 +775,24 @@ int unload_module()
|
||||
p = p->next;
|
||||
}
|
||||
iflist = NULL;
|
||||
ast_pthread_mutex_unlock(&iflock);
|
||||
pthread_mutex_unlock(&iflock);
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Unable to lock the monitor\n");
|
||||
return -1;
|
||||
}
|
||||
if (!ast_pthread_mutex_lock(&monlock)) {
|
||||
if (!pthread_mutex_lock(&monlock)) {
|
||||
if (monitor_thread > -1) {
|
||||
pthread_cancel(monitor_thread);
|
||||
pthread_join(monitor_thread, NULL);
|
||||
}
|
||||
monitor_thread = -2;
|
||||
ast_pthread_mutex_unlock(&monlock);
|
||||
pthread_mutex_unlock(&monlock);
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Unable to lock the monitor\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!ast_pthread_mutex_lock(&iflock)) {
|
||||
if (!pthread_mutex_lock(&iflock)) {
|
||||
/* Destroy all the interfaces and free their memory */
|
||||
p = iflist;
|
||||
while(p) {
|
||||
@@ -883,7 +805,7 @@ int unload_module()
|
||||
free(pl);
|
||||
}
|
||||
iflist = NULL;
|
||||
ast_pthread_mutex_unlock(&iflock);
|
||||
pthread_mutex_unlock(&iflock);
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Unable to lock the monitor\n");
|
||||
return -1;
|
||||
@@ -895,9 +817,9 @@ int unload_module()
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
ast_pthread_mutex_lock(&usecnt_lock);
|
||||
pthread_mutex_lock(&usecnt_lock);
|
||||
res = usecnt;
|
||||
ast_pthread_mutex_unlock(&usecnt_lock);
|
||||
pthread_mutex_unlock(&usecnt_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -906,8 +828,3 @@ char *description()
|
||||
return desc;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
|
||||
@@ -363,17 +363,17 @@ static char *aopen_identify(struct ast_modem_pvt *p)
|
||||
|
||||
static void aopen_incusecnt()
|
||||
{
|
||||
ast_pthread_mutex_lock(&usecnt_lock);
|
||||
pthread_mutex_lock(&usecnt_lock);
|
||||
usecnt++;
|
||||
ast_pthread_mutex_unlock(&usecnt_lock);
|
||||
pthread_mutex_unlock(&usecnt_lock);
|
||||
ast_update_use_count();
|
||||
}
|
||||
|
||||
static void aopen_decusecnt()
|
||||
{
|
||||
ast_pthread_mutex_lock(&usecnt_lock);
|
||||
pthread_mutex_lock(&usecnt_lock);
|
||||
usecnt++;
|
||||
ast_pthread_mutex_unlock(&usecnt_lock);
|
||||
pthread_mutex_unlock(&usecnt_lock);
|
||||
ast_update_use_count();
|
||||
}
|
||||
|
||||
@@ -457,9 +457,9 @@ static struct ast_modem_driver aopen_driver =
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
ast_pthread_mutex_lock(&usecnt_lock);
|
||||
pthread_mutex_lock(&usecnt_lock);
|
||||
res = usecnt;
|
||||
ast_pthread_mutex_unlock(&usecnt_lock);
|
||||
pthread_mutex_unlock(&usecnt_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -478,7 +478,3 @@ char *description()
|
||||
return desc;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
@@ -1,596 +0,0 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* BestData 56SX-92 Voice Modem Driver (Conexant)
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer and 2001 Jim Dixon
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
* Jim Dixon <jim@lambdatel.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <asterisk/vmodem.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/frame.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/options.h>
|
||||
|
||||
#define STATE_COMMAND 0
|
||||
#define STATE_VOICE 1
|
||||
#define STATE_VOICEPLAY 2
|
||||
|
||||
#define VRA "40" /* Number of 100ms of non-ring after a ring cadence after which we consider the lien to be answered */
|
||||
#define VRN "25" /* Number of 100ms of non-ring with no cadence after which we assume an answer */
|
||||
|
||||
#define RINGT 7000
|
||||
|
||||
static char *breakcmd = "\020!";
|
||||
|
||||
static char *desc = "BestData (Conexant V.90 Chipset) VoiceModem Driver";
|
||||
|
||||
int usecnt;
|
||||
pthread_mutex_t usecnt_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
static char *bestdata_idents[] = {
|
||||
/* Identify BestData Modem */
|
||||
"ACF3_V1.010-V90_P21_FSH",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int bestdata_startrec(struct ast_modem_pvt *p)
|
||||
{
|
||||
static int bestdata_break(struct ast_modem_pvt *p);
|
||||
|
||||
if (p->ministate != STATE_COMMAND) bestdata_break(p);
|
||||
if (ast_modem_send(p, "AT+VRX", 0) ||
|
||||
ast_modem_expect(p, "CONNECT", 5)) {
|
||||
ast_log(LOG_WARNING, "Unable to start recording\n");
|
||||
return -1;
|
||||
}
|
||||
p->ministate = STATE_VOICE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bestdata_startplay(struct ast_modem_pvt *p)
|
||||
{
|
||||
static int bestdata_break(struct ast_modem_pvt *p);
|
||||
|
||||
if (p->ministate != STATE_COMMAND) bestdata_break(p);
|
||||
if (ast_modem_send(p, "AT+VTX", 0) ||
|
||||
ast_modem_expect(p, "CONNECT", 5)) {
|
||||
ast_log(LOG_WARNING, "Unable to start recording\n");
|
||||
return -1;
|
||||
}
|
||||
p->ministate = STATE_VOICEPLAY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bestdata_break(struct ast_modem_pvt *p)
|
||||
{
|
||||
if (ast_modem_send(p, breakcmd, 2)) {
|
||||
ast_log(LOG_WARNING, "Failed to break\n");
|
||||
return -1;
|
||||
}
|
||||
p->ministate = STATE_COMMAND;
|
||||
usleep(10000);
|
||||
/* Read any outstanding junk */
|
||||
while(!ast_modem_read_response(p, 1));
|
||||
if (ast_modem_send(p, "AT", 0)) {
|
||||
/* Modem might be stuck in some weird mode, try to get it out */
|
||||
ast_modem_send(p, "+++", 3);
|
||||
if (ast_modem_expect(p, "OK", 10)) {
|
||||
ast_log(LOG_WARNING, "Modem is not responding\n");
|
||||
return -1;
|
||||
}
|
||||
if (ast_modem_send(p, "AT", 0)) {
|
||||
ast_log(LOG_WARNING, "Modem is not responding\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (ast_modem_expect(p, "OK", 5)) {
|
||||
ast_log(LOG_WARNING, "Modem did not respond properly\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bestdata_init(struct ast_modem_pvt *p)
|
||||
{
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "bestdata_init()\n");
|
||||
if (bestdata_break(p))
|
||||
return -1;
|
||||
/* Force into command mode */
|
||||
p->ministate = STATE_COMMAND;
|
||||
if (ast_modem_send(p, "AT+FCLASS=8", 0) ||
|
||||
ast_modem_expect(p, "OK", 5)) {
|
||||
ast_log(LOG_WARNING, "Unable to set to voice mode\n");
|
||||
return -1;
|
||||
}
|
||||
if (ast_modem_send(p, "AT+VSM=1,8000,0,0", 0) ||
|
||||
ast_modem_expect(p, "OK", 5)) {
|
||||
ast_log(LOG_WARNING, "Unable to set to 8000 Hz sampling\n");
|
||||
return -1;
|
||||
}
|
||||
if (ast_modem_send(p, "AT+VLS=0", 0) ||
|
||||
ast_modem_expect(p, "OK", 5)) {
|
||||
ast_log(LOG_WARNING, "Unable to set to telco interface\n");
|
||||
return -1;
|
||||
}
|
||||
if (ast_modem_send(p, "AT+VRA=" VRA, 0) ||
|
||||
ast_modem_expect(p, "OK", 5)) {
|
||||
ast_log(LOG_WARNING, "Unable to set to 'ringback goes away' timer\n");
|
||||
return -1;
|
||||
}
|
||||
if (ast_modem_send(p, "AT+VRN=" VRN, 0) ||
|
||||
ast_modem_expect(p, "OK", 5)) {
|
||||
ast_log(LOG_WARNING, "Unable to set to 'ringback never came timer'\n");
|
||||
return -1;
|
||||
}
|
||||
if (ast_modem_send(p, "AT+VTD=63", 0) ||
|
||||
ast_modem_expect(p, "OK", 5)) {
|
||||
ast_log(LOG_WARNING, "Unable to set to tone detection\n");
|
||||
return -1;
|
||||
}
|
||||
if (ast_modem_send(p, "AT+VCID=1", 0) ||
|
||||
ast_modem_expect(p, "OK", 5)) {
|
||||
ast_log(LOG_WARNING, "Unable to enable Caller*ID\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ast_frame *bestdata_handle_escape(struct ast_modem_pvt *p, char esc)
|
||||
{
|
||||
char name[30],nmbr[30];
|
||||
time_t now;
|
||||
|
||||
/* Handle escaped characters -- but sometimes we call it directly as
|
||||
a quick way to cause known responses */
|
||||
p->fr.frametype = AST_FRAME_NULL;
|
||||
p->fr.subclass = 0;
|
||||
p->fr.data = NULL;
|
||||
p->fr.datalen = 0;
|
||||
p->fr.timelen = 0;
|
||||
p->fr.offset = 0;
|
||||
p->fr.mallocd = 0;
|
||||
if (esc)
|
||||
ast_log(LOG_DEBUG, "Escaped character '%c'\n", esc);
|
||||
|
||||
switch(esc) {
|
||||
case 'R': /* Pseudo ring */
|
||||
time(&now);
|
||||
if (now > (p->lastring + (RINGT / 1000)))
|
||||
{ /* if stale, treat as new */
|
||||
p->gotclid = 0;
|
||||
}
|
||||
if (p->gotclid)
|
||||
{
|
||||
p->fr.frametype = AST_FRAME_CONTROL;
|
||||
p->fr.subclass = AST_CONTROL_RING;
|
||||
}
|
||||
p->ringt = RINGT;
|
||||
time(&p->lastring);
|
||||
return &p->fr;
|
||||
case 'X': /* Caller-ID Spill */
|
||||
if (p->gotclid) return &p->fr;
|
||||
name[0] = nmbr[0] = 0;
|
||||
for(;;)
|
||||
{
|
||||
char res[1000];
|
||||
|
||||
if (ast_modem_read_response(p, 5)) break;
|
||||
strncpy(res, p->response, sizeof(res));
|
||||
ast_modem_trim(res);
|
||||
if (!strncmp(res,"\020.",2)) break;
|
||||
if (!strncmp(res,"NAME",4)) strcpy(name,res + 7);
|
||||
if (!strncmp(res,"NMBR",4)) strcpy(nmbr,res + 7);
|
||||
}
|
||||
p->gotclid = 1;
|
||||
if ((!strcmp(name,"O")) || (!strcmp(name,"P"))) name[0] = 0;
|
||||
if ((!strcmp(nmbr,"O")) || (!strcmp(nmbr,"P"))) nmbr[0] = 0;
|
||||
if ((name[0]) && (nmbr[0])) snprintf(p->cid,sizeof(p->cid),
|
||||
"\"%s\" <%s>",name,nmbr);
|
||||
else if (name[0]) snprintf(p->cid,sizeof(p->cid),
|
||||
"\"%s\"",name);
|
||||
else if (nmbr[0]) snprintf(p->cid,sizeof(p->cid),
|
||||
"%s",nmbr);
|
||||
if (p->owner) p->owner->callerid = strdup(p->cid);
|
||||
return &p->fr;
|
||||
case '@': /* response from "OK" in command mode */
|
||||
if (p->owner)
|
||||
p->owner->state = AST_STATE_UP;
|
||||
if (bestdata_startrec(p)) return NULL;
|
||||
p->fr.frametype = AST_FRAME_CONTROL;
|
||||
p->fr.subclass = AST_CONTROL_RING;
|
||||
return &p->fr;
|
||||
case 'b': /* Busy signal */
|
||||
p->fr.frametype = AST_FRAME_CONTROL;
|
||||
p->fr.subclass = AST_CONTROL_BUSY;
|
||||
return &p->fr;
|
||||
case 'o': /* Overrun */
|
||||
ast_log(LOG_WARNING, "Overflow on modem, flushing buffers\n");
|
||||
if (ast_modem_send(p, "\0x10E", 2))
|
||||
ast_log(LOG_WARNING, "Unable to flush buffers\n");
|
||||
return &p->fr;
|
||||
case '0': /* All the DTMF characters */
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case '*':
|
||||
case '#':
|
||||
case 'A':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'D':
|
||||
p->dtmfrx = esc; /* save this for when its done */
|
||||
return &p->fr;
|
||||
case '/': /* Start of DTMF tone shielding */
|
||||
p->dtmfrx = ' ';
|
||||
return &p->fr;
|
||||
case '~': /* DTMF transition to off */
|
||||
if (p->dtmfrx > ' ')
|
||||
{
|
||||
p->fr.frametype = AST_FRAME_DTMF;
|
||||
p->fr.subclass = p->dtmfrx;
|
||||
}
|
||||
p->dtmfrx = 0;
|
||||
return &p->fr;
|
||||
case 'u': /* Underrun */
|
||||
ast_log(LOG_WARNING, "Data underrun\n");
|
||||
/* Fall Through */
|
||||
case CHAR_ETX: /* End Transmission */
|
||||
case 'd': /* Dialtone */
|
||||
case 'c': /* Calling Tone */
|
||||
case 'e': /* European version */
|
||||
case 'a': /* Answer Tone */
|
||||
case 'f': /* Bell Answer Tone */
|
||||
case 'T': /* Timing mark */
|
||||
case 't': /* Handset off hook */
|
||||
case 'h': /* Handset hungup */
|
||||
case 0: /* Pseudo signal */
|
||||
/* Ignore */
|
||||
return &p->fr;
|
||||
default:
|
||||
ast_log(LOG_DEBUG, "Unknown Escaped character '%c' (%d)\n", esc, esc);
|
||||
}
|
||||
return &p->fr;
|
||||
}
|
||||
|
||||
static struct ast_frame *bestdata_read(struct ast_modem_pvt *p)
|
||||
{
|
||||
char result[256];
|
||||
short *b;
|
||||
struct ast_frame *f=NULL;
|
||||
int res;
|
||||
int x;
|
||||
|
||||
if (p->ministate == STATE_COMMAND) {
|
||||
/* Read the first two bytes, first, in case it's a control message */
|
||||
fread(result, 1, 2, p->f);
|
||||
if (result[0] == CHAR_DLE) {
|
||||
return bestdata_handle_escape(p, result[1]);
|
||||
} else {
|
||||
if (p->ringt) /* if ring timeout specified */
|
||||
{
|
||||
x = fileno(p->f);
|
||||
res = ast_waitfor_n_fd(&x, 1, &p->ringt, NULL);
|
||||
if (res < 0) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if ((result[0] == '\n') || (result[0] == '\r'))
|
||||
return bestdata_handle_escape(p, 0);
|
||||
/* Read the rest of the line */
|
||||
fgets(result + 2, sizeof(result) - 2, p->f);
|
||||
ast_modem_trim(result);
|
||||
if (!strcasecmp(result, "OK")) {
|
||||
/* If we're in immediate mode, reply now */
|
||||
if (p->mode == MODEM_MODE_IMMEDIATE)
|
||||
return bestdata_handle_escape(p, '@');
|
||||
} else
|
||||
if (!strcasecmp(result, "BUSY")) {
|
||||
/* Same as a busy signal */
|
||||
return bestdata_handle_escape(p, 'b');
|
||||
} else
|
||||
if (!strcasecmp(result, "RING")) {
|
||||
return bestdata_handle_escape(p, 'R');
|
||||
} else
|
||||
if (!strcasecmp(result, "NO DIALTONE")) {
|
||||
/* There's no dialtone, so the line isn't working */
|
||||
ast_log(LOG_WARNING, "Device '%s' lacking dialtone\n", p->dev);
|
||||
return NULL;
|
||||
}
|
||||
ast_log(LOG_DEBUG, "Modem said '%s'\n", result);
|
||||
return bestdata_handle_escape(p, 0);
|
||||
}
|
||||
} else {
|
||||
/* if playing, start recording instead */
|
||||
if (p->ministate == STATE_VOICEPLAY)
|
||||
{
|
||||
if (bestdata_startrec(p)) return NULL;
|
||||
}
|
||||
/* We have to be more efficient in voice mode */
|
||||
b = (short *)(p->obuf + p->obuflen);
|
||||
while (p->obuflen/2 < 240) {
|
||||
/* Read ahead the full amount */
|
||||
res = fread(result, 1, 240 - p->obuflen/2, p->f);
|
||||
if (res < 1) {
|
||||
/* If there's nothing there, just continue on */
|
||||
if (errno == EAGAIN)
|
||||
return bestdata_handle_escape(p, 0);
|
||||
ast_log(LOG_WARNING, "Read failed: %s\n", strerror(errno));
|
||||
}
|
||||
for (x=0;x<res;x++) {
|
||||
/* Process all the bytes that we've read */
|
||||
if (result[x] == CHAR_DLE) {
|
||||
/* We assume there is no more than one signal frame among our
|
||||
data. */
|
||||
if (f) ast_log(LOG_WARNING, "Warning: Dropped a signal frame\n");
|
||||
/* if not a DLE in the data */
|
||||
if (result[++x] != CHAR_DLE)
|
||||
{
|
||||
/* If bestdata_handle_escape says NULL, say it now, doesn't matter
|
||||
what else is there, the connection is dead. */
|
||||
f = bestdata_handle_escape(p, result[x]);
|
||||
if (p->dtmfrx) continue;
|
||||
return(f);
|
||||
}
|
||||
}
|
||||
/* Generate a 16-bit signed linear value from our
|
||||
unsigned 8-bit value */
|
||||
*(b++) = (((short)result[x]) - 127) * 0xff;
|
||||
p->obuflen += 2;
|
||||
}
|
||||
if (f) break;
|
||||
}
|
||||
/* If we have a control frame, return it now */
|
||||
if (f) return f;
|
||||
/* If we get here, we have a complete voice frame */
|
||||
p->fr.frametype = AST_FRAME_VOICE;
|
||||
p->fr.subclass = AST_FORMAT_SLINEAR;
|
||||
p->fr.timelen = 30;
|
||||
p->fr.data = p->obuf;
|
||||
p->fr.datalen = p->obuflen;
|
||||
p->fr.mallocd = 0;
|
||||
p->fr.offset = AST_FRIENDLY_OFFSET;
|
||||
p->fr.src = __FUNCTION__;
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "bestdata_read(voice frame)\n");
|
||||
p->obuflen = 0;
|
||||
return &p->fr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int bestdata_write(struct ast_modem_pvt *p, struct ast_frame *f)
|
||||
{
|
||||
unsigned char c,buf[32768]; /* I hope we dont have frames larger then 16K */
|
||||
int i,j;
|
||||
short *sp;
|
||||
unsigned long u;
|
||||
#define DLE 16
|
||||
|
||||
if (p->owner && (p->owner->state == AST_STATE_UP) &&
|
||||
(p->ministate != STATE_VOICEPLAY) && bestdata_startplay(p)) return -1;
|
||||
sp = (short *) f->data;
|
||||
/* stick DLE's in ahead of anything else */
|
||||
for(i = 0,j = 0; i < f->datalen / 2; i++)
|
||||
{
|
||||
*sp *= 3;
|
||||
u = *sp++ + 32768;
|
||||
c = u >> 8;
|
||||
if (c == DLE) buf[j++] = DLE;
|
||||
buf[j++] = c;
|
||||
}
|
||||
do i = fwrite(buf,1,j,p->f);
|
||||
while ((i == -1) && (errno == EWOULDBLOCK));
|
||||
if (i != j)
|
||||
{
|
||||
ast_log(LOG_WARNING,"modem short write!!\n");
|
||||
return -1;
|
||||
}
|
||||
fflush(p->f);
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "bestdata_write()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *bestdata_identify(struct ast_modem_pvt *p)
|
||||
{
|
||||
char identity[256];
|
||||
char mfr[80];
|
||||
char mdl[80];
|
||||
char rev[80];
|
||||
ast_modem_send(p, "AT+FMM", 0);
|
||||
ast_modem_read_response(p, 5);
|
||||
strncpy(mdl, p->response, sizeof(mdl));
|
||||
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));
|
||||
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));
|
||||
ast_modem_trim(rev);
|
||||
ast_modem_expect(p, "OK", 5);
|
||||
snprintf(identity, sizeof(identity), "%s Model %s Revision %s", mfr, mdl, rev);
|
||||
return strdup(identity);
|
||||
}
|
||||
|
||||
static void bestdata_incusecnt()
|
||||
{
|
||||
ast_pthread_mutex_lock(&usecnt_lock);
|
||||
usecnt++;
|
||||
ast_pthread_mutex_unlock(&usecnt_lock);
|
||||
ast_update_use_count();
|
||||
}
|
||||
|
||||
static void bestdata_decusecnt()
|
||||
{
|
||||
ast_pthread_mutex_lock(&usecnt_lock);
|
||||
usecnt++;
|
||||
ast_pthread_mutex_unlock(&usecnt_lock);
|
||||
ast_update_use_count();
|
||||
}
|
||||
|
||||
static int bestdata_answer(struct ast_modem_pvt *p)
|
||||
{
|
||||
p->ringt = 0;
|
||||
p->lastring = 0;
|
||||
if (ast_modem_send(p, "AT+VLS=1", 0) ||
|
||||
ast_modem_expect(p, "OK", 10)) {
|
||||
ast_log(LOG_WARNING, "Unable to answer: %s", p->response);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bestdata_dialdigit(struct ast_modem_pvt *p, char digit)
|
||||
{
|
||||
char cmd[80];
|
||||
|
||||
if (p->ministate != STATE_COMMAND) bestdata_break(p);
|
||||
snprintf(cmd, sizeof(cmd), "AT+VTS=%c", digit);
|
||||
if (ast_modem_send(p, cmd, 0) ||
|
||||
ast_modem_expect(p, "OK", 10)) {
|
||||
ast_log(LOG_WARNING, "Unable to answer: %s", p->response);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bestdata_dial(struct ast_modem_pvt *p, char *stuff)
|
||||
{
|
||||
char cmd[800],a[20];
|
||||
int i,j;
|
||||
|
||||
if (p->ministate != STATE_COMMAND)
|
||||
{
|
||||
bestdata_break(p);
|
||||
strcpy(cmd,"AT+VTS=");
|
||||
j = strlen(cmd);
|
||||
for(i = 0; stuff[i]; i++)
|
||||
{
|
||||
switch(stuff[i])
|
||||
{
|
||||
case '!' :
|
||||
a[0] = stuff[i];
|
||||
a[1] = 0;
|
||||
break;
|
||||
case ',':
|
||||
strcpy(a,"[,,100]");
|
||||
break;
|
||||
default:
|
||||
sprintf(a,"{%c,7}",stuff[i]);
|
||||
}
|
||||
if (stuff[i + 1]) strcat(a,",");
|
||||
strcpy(cmd + j,a);
|
||||
j += strlen(a);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(cmd, sizeof(cmd), "ATD%c %s", p->dialtype,stuff);
|
||||
}
|
||||
if (ast_modem_send(p, cmd, 0)) {
|
||||
ast_log(LOG_WARNING, "Unable to dial\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bestdata_hangup(struct ast_modem_pvt *p)
|
||||
{
|
||||
if (bestdata_break(p))
|
||||
return -1;
|
||||
/* Hangup by switching to data, then back to voice */
|
||||
if (ast_modem_send(p, "ATH", 0) ||
|
||||
ast_modem_expect(p, "OK", 8)) {
|
||||
ast_log(LOG_WARNING, "Unable to set to data mode\n");
|
||||
return -1;
|
||||
}
|
||||
if (ast_modem_send(p, "AT+FCLASS=8", 0) ||
|
||||
ast_modem_expect(p, "OK", 5)) {
|
||||
ast_log(LOG_WARNING, "Unable to set to voice mode\n");
|
||||
return -1;
|
||||
}
|
||||
p->gotclid = 0;
|
||||
p->ringt = 0;
|
||||
p->lastring = 0;
|
||||
p->dtmfrx = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ast_modem_driver bestdata_driver =
|
||||
{
|
||||
"BestData",
|
||||
bestdata_idents,
|
||||
AST_FORMAT_SLINEAR,
|
||||
0, /* Not full duplex */
|
||||
bestdata_incusecnt, /* incusecnt */
|
||||
bestdata_decusecnt, /* decusecnt */
|
||||
bestdata_identify, /* identify */
|
||||
bestdata_init, /* init */
|
||||
NULL, /* setdev */
|
||||
bestdata_read,
|
||||
bestdata_write,
|
||||
bestdata_dial, /* dial */
|
||||
bestdata_answer, /* answer */
|
||||
bestdata_hangup, /* hangup */
|
||||
bestdata_startrec, /* start record */
|
||||
NULL, /* stop record */
|
||||
bestdata_startplay, /* start playback */
|
||||
NULL, /* stop playback */
|
||||
NULL, /* set silence supression */
|
||||
bestdata_dialdigit, /* dialdigit */
|
||||
};
|
||||
|
||||
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
ast_pthread_mutex_lock(&usecnt_lock);
|
||||
res = usecnt;
|
||||
ast_pthread_mutex_unlock(&usecnt_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_modem_driver(&bestdata_driver);
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
return ast_unregister_modem_driver(&bestdata_driver);
|
||||
}
|
||||
|
||||
char *description()
|
||||
{
|
||||
return desc;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
@@ -1,578 +0,0 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* ISDN4Linux TTY Driver
|
||||
*
|
||||
* Copyright (C) 2001, 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 <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <asterisk/vmodem.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/frame.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/options.h>
|
||||
#include "alaw.h"
|
||||
|
||||
#define STATE_COMMAND 0
|
||||
#define STATE_VOICE 1
|
||||
|
||||
static char *breakcmd = "\0x10\0x14\0x10\0x3";
|
||||
|
||||
static char *desc = "ISDN4Linux Emulated Modem Driver";
|
||||
|
||||
int usecnt;
|
||||
pthread_mutex_t usecnt_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
static char *i4l_idents[] = {
|
||||
/* Identify ISDN4Linux Driver */
|
||||
"Linux ISDN",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int i4l_setdev(struct ast_modem_pvt *p, int dev)
|
||||
{
|
||||
char cmd[80];
|
||||
if ((dev != MODEM_DEV_TELCO) && (dev != MODEM_DEV_TELCO_SPK)) {
|
||||
ast_log(LOG_WARNING, "ISDN4Linux only supports telco device, not %d.\n", dev);
|
||||
return -1;
|
||||
} else /* Convert DEV to our understanding of it */
|
||||
dev = 2;
|
||||
if (ast_modem_send(p, "AT+VLS?", 0)) {
|
||||
ast_log(LOG_WARNING, "Unable to select current mode %d\n", dev);
|
||||
return -1;
|
||||
}
|
||||
if (ast_modem_read_response(p, 5)) {
|
||||
ast_log(LOG_WARNING, "Unable to select device %d\n", dev);
|
||||
return -1;
|
||||
}
|
||||
ast_modem_trim(p->response);
|
||||
strncpy(cmd, p->response, sizeof(cmd));
|
||||
if (ast_modem_expect(p, "OK", 5)) {
|
||||
ast_log(LOG_WARNING, "Modem did not respond properly\n");
|
||||
return -1;
|
||||
}
|
||||
if (dev == atoi(cmd)) {
|
||||
/* We're already in the right mode, don't bother changing for fear of
|
||||
hanging up */
|
||||
return 0;
|
||||
}
|
||||
snprintf(cmd, sizeof(cmd), "AT+VLS=%d", dev);
|
||||
if (ast_modem_send(p, cmd, 0)) {
|
||||
ast_log(LOG_WARNING, "Unable to select device %d\n", dev);
|
||||
return -1;
|
||||
}
|
||||
if (ast_modem_read_response(p, 5)) {
|
||||
ast_log(LOG_WARNING, "Unable to select device %d\n", dev);
|
||||
return -1;
|
||||
}
|
||||
ast_modem_trim(p->response);
|
||||
if (strcasecmp(p->response, "VCON") && strcasecmp(p->response, "OK")) {
|
||||
ast_log(LOG_WARNING, "Unexpected reply: %s\n", p->response);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i4l_startrec(struct ast_modem_pvt *p)
|
||||
{
|
||||
if (ast_modem_send(p, "AT+VRX+VTX", 0) ||
|
||||
ast_modem_expect(p, "CONNECT", 5)) {
|
||||
ast_log(LOG_WARNING, "Unable to start recording\n");
|
||||
return -1;
|
||||
}
|
||||
p->ministate = STATE_VOICE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i4l_break(struct ast_modem_pvt *p)
|
||||
{
|
||||
if (ast_modem_send(p, breakcmd, 2)) {
|
||||
ast_log(LOG_WARNING, "Failed to break\n");
|
||||
return -1;
|
||||
}
|
||||
if (ast_modem_send(p, "\r\n", 2)) {
|
||||
ast_log(LOG_WARNING, "Failed to send enter?\n");
|
||||
return -1;
|
||||
}
|
||||
#if 0
|
||||
/* Read any outstanding junk */
|
||||
while(!ast_modem_read_response(p, 1));
|
||||
#endif
|
||||
if (ast_modem_send(p, "AT", 0)) {
|
||||
/* Modem might be stuck in some weird mode, try to get it out */
|
||||
ast_modem_send(p, "+++", 3);
|
||||
if (ast_modem_expect(p, "OK", 10)) {
|
||||
ast_log(LOG_WARNING, "Modem is not responding\n");
|
||||
return -1;
|
||||
}
|
||||
if (ast_modem_send(p, "AT", 0)) {
|
||||
ast_log(LOG_WARNING, "Modem is not responding\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (ast_modem_expect(p, "OK", 5)) {
|
||||
ast_log(LOG_WARNING, "Modem did not respond properly\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i4l_init(struct ast_modem_pvt *p)
|
||||
{
|
||||
char cmd[256];
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "i4l_init()\n");
|
||||
if (i4l_break(p))
|
||||
return -1;
|
||||
/* Force into command mode */
|
||||
p->ministate = STATE_COMMAND;
|
||||
if (ast_modem_send(p, "AT+FCLASS=8", 0) ||
|
||||
ast_modem_expect(p, "OK", 5)) {
|
||||
ast_log(LOG_WARNING, "Unable to set to voice mode\n");
|
||||
return -1;
|
||||
}
|
||||
if (strlen(p->msn)) {
|
||||
snprintf(cmd, sizeof(cmd), "AT&E%s", p->msn);
|
||||
if (ast_modem_send(p, cmd, 0) ||
|
||||
ast_modem_expect(p, "OK", 5)) {
|
||||
ast_log(LOG_WARNING, "Unable to set MSN to %s\n", p->msn);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (ast_modem_send(p, "ATS18=1", 0) ||
|
||||
ast_modem_expect(p, "OK", 5)) {
|
||||
ast_log(LOG_WARNING, "Unable to set to audio only mode\n");
|
||||
return -1;
|
||||
}
|
||||
if (ast_modem_send(p, "ATS14=4", 0) ||
|
||||
ast_modem_expect(p, "OK", 5)) {
|
||||
ast_log(LOG_WARNING, "Unable to set to transparent mode\n");
|
||||
return -1;
|
||||
}
|
||||
if (ast_modem_send(p, "ATS23=1", 0) ||
|
||||
ast_modem_expect(p, "OK", 5)) {
|
||||
ast_log(LOG_WARNING, "Unable to set to transparent mode\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ast_modem_send(p, "AT+VSM=5", 0) ||
|
||||
ast_modem_expect(p, "OK", 5)) {
|
||||
ast_log(LOG_WARNING, "Unable to set to aLAW mode\n");
|
||||
return -1;
|
||||
}
|
||||
if (ast_modem_send(p, "AT+VLS=2", 0) ||
|
||||
ast_modem_expect(p, "OK", 5)) {
|
||||
ast_log(LOG_WARNING, "Unable to set to phone line interface\n");
|
||||
return -1;
|
||||
}
|
||||
p->escape = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ast_frame *i4l_handle_escape(struct ast_modem_pvt *p, char esc)
|
||||
{
|
||||
/* Handle escaped characters -- but sometimes we call it directly as
|
||||
a quick way to cause known responses */
|
||||
p->fr.frametype = AST_FRAME_NULL;
|
||||
p->fr.subclass = 0;
|
||||
p->fr.data = NULL;
|
||||
p->fr.datalen = 0;
|
||||
p->fr.timelen = 0;
|
||||
p->fr.offset = 0;
|
||||
p->fr.mallocd = 0;
|
||||
if (esc && option_debug)
|
||||
ast_log(LOG_DEBUG, "Escaped character '%c'\n", esc);
|
||||
|
||||
switch(esc) {
|
||||
case 'R': /* Pseudo ring */
|
||||
p->fr.frametype = AST_FRAME_CONTROL;
|
||||
p->fr.subclass = AST_CONTROL_RING;
|
||||
return &p->fr;
|
||||
case 'X': /* Pseudo connect */
|
||||
p->fr.frametype = AST_FRAME_CONTROL;
|
||||
p->fr.subclass = AST_CONTROL_ANSWER;
|
||||
if (p->owner)
|
||||
p->owner->state = AST_STATE_UP;
|
||||
if (i4l_startrec(p))
|
||||
return NULL;
|
||||
return &p->fr;
|
||||
case 'b': /* Busy signal */
|
||||
p->fr.frametype = AST_FRAME_CONTROL;
|
||||
p->fr.subclass = AST_CONTROL_BUSY;
|
||||
return &p->fr;
|
||||
case 'o': /* Overrun */
|
||||
ast_log(LOG_WARNING, "Overflow on modem, flushing buffers\n");
|
||||
if (ast_modem_send(p, "\0x10E", 2))
|
||||
ast_log(LOG_WARNING, "Unable to flush buffers\n");
|
||||
return &p->fr;
|
||||
case CHAR_ETX: /* End Transmission */
|
||||
return NULL;
|
||||
case 'u': /* Underrun */
|
||||
ast_log(LOG_WARNING, "Data underrun\n");
|
||||
/* Fall Through */
|
||||
case 'd': /* Dialtone */
|
||||
case 'c': /* Calling Tone */
|
||||
case 'e': /* European version */
|
||||
case 'a': /* Answer Tone */
|
||||
case 'f': /* Bell Answer Tone */
|
||||
case 'T': /* Timing mark */
|
||||
case 't': /* Handset off hook */
|
||||
case 'h': /* Handset hungup */
|
||||
/* Ignore */
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "Ignoring Escaped character '%c' (%d)\n", esc, esc);
|
||||
return &p->fr;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case '*':
|
||||
case '#':
|
||||
ast_log(LOG_DEBUG, "DTMF: '%c' (%d)\n", esc, esc);
|
||||
p->fr.frametype=AST_FRAME_DTMF;
|
||||
p->fr.subclass=esc;
|
||||
return &p->fr;
|
||||
case 0: /* Pseudo signal */
|
||||
return &p->fr;
|
||||
default:
|
||||
ast_log(LOG_DEBUG, "Unknown Escaped character '%c' (%d)\n", esc, esc);
|
||||
}
|
||||
return &p->fr;
|
||||
}
|
||||
|
||||
static struct ast_frame *i4l_read(struct ast_modem_pvt *p)
|
||||
{
|
||||
char result[256];
|
||||
short *b;
|
||||
struct ast_frame *f=NULL;
|
||||
int res;
|
||||
int x;
|
||||
if (p->ministate == STATE_COMMAND) {
|
||||
/* Read the first two bytes, first, in case it's a control message */
|
||||
read(p->fd, result, 2);
|
||||
if (result[0] == CHAR_DLE) {
|
||||
return i4l_handle_escape(p, result[1]);
|
||||
|
||||
} else {
|
||||
if ((result[0] == '\n') || (result[0] == '\r'))
|
||||
return i4l_handle_escape(p, 0);
|
||||
/* Read the rest of the line */
|
||||
fgets(result + 2, sizeof(result) - 2, p->f);
|
||||
ast_modem_trim(result);
|
||||
if (!strcasecmp(result, "VCON")) {
|
||||
/* If we're in immediate mode, reply now */
|
||||
if (p->mode == MODEM_MODE_IMMEDIATE)
|
||||
return i4l_handle_escape(p, 'X');
|
||||
} else
|
||||
if (!strcasecmp(result, "BUSY")) {
|
||||
/* Same as a busy signal */
|
||||
return i4l_handle_escape(p, 'b');
|
||||
} else
|
||||
if (!strncasecmp(result, "CALLER NUMBER: ", 15 )) {
|
||||
strncpy(p->cid, result + 15, sizeof(p->cid));
|
||||
return i4l_handle_escape(p, 'R');
|
||||
} else
|
||||
if (!strncasecmp(result, "RING", 4)) {
|
||||
if (result[4]=='/')
|
||||
strncpy(p->dnid, result + 4, sizeof(p->dnid));
|
||||
return i4l_handle_escape(p, 'R');
|
||||
} else
|
||||
if (!strcasecmp(result, "NO CARRIER")) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "%s hung up on\n", p->dev);
|
||||
return NULL;
|
||||
} else
|
||||
if (!strcasecmp(result, "NO DIALTONE")) {
|
||||
/* There's no dialtone, so the line isn't working */
|
||||
ast_log(LOG_WARNING, "Device '%s' lacking dialtone\n", p->dev);
|
||||
return NULL;
|
||||
}
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "Modem said '%s'\n", result);
|
||||
return i4l_handle_escape(p, 0);
|
||||
}
|
||||
} else {
|
||||
/* We have to be more efficient in voice mode */
|
||||
b = (short *)(p->obuf + p->obuflen);
|
||||
while (p->obuflen/2 < 240) {
|
||||
/* Read ahead the full amount */
|
||||
res = read(p->fd, result, 240 - p->obuflen/2);
|
||||
if (res < 1) {
|
||||
/* If there's nothing there, just continue on */
|
||||
if (errno == EAGAIN)
|
||||
return i4l_handle_escape(p, 0);
|
||||
ast_log(LOG_WARNING, "Read failed: %s\n", strerror(errno));
|
||||
}
|
||||
|
||||
for (x=0;x<res;x++) {
|
||||
/* Process all the bytes that we've read */
|
||||
switch(result[x]) {
|
||||
case CHAR_DLE:
|
||||
#if 0
|
||||
ast_log(LOG_DEBUG, "Ooh, an escape at %d...\n", x);
|
||||
#endif
|
||||
if (!p->escape) {
|
||||
/* Note that next value is
|
||||
an escape, and continue. */
|
||||
p->escape++;
|
||||
break;
|
||||
} else {
|
||||
/* Send as is -- fallthrough */
|
||||
p->escape = 0;
|
||||
}
|
||||
default:
|
||||
if (p->escape) {
|
||||
ast_log(LOG_DEBUG, "Value of escape is %c (%d)...\n", result[x] < 32 ? '^' : result[x], result[x]);
|
||||
p->escape = 0;
|
||||
if (f)
|
||||
ast_log(LOG_WARNING, "Warning: Dropped a signal frame\n");
|
||||
f = i4l_handle_escape(p, result[x]);
|
||||
/* If i4l_handle_escape says NULL, say it now, doesn't matter
|
||||
what else is there, the connection is dead. */
|
||||
if (!f)
|
||||
return NULL;
|
||||
} else {
|
||||
*(b++) = ALAW2INT(result[x] & 0xff);
|
||||
p->obuflen += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (f)
|
||||
break;
|
||||
}
|
||||
if (f)
|
||||
return f;
|
||||
/* If we get here, we have a complete voice frame */
|
||||
p->fr.frametype = AST_FRAME_VOICE;
|
||||
p->fr.subclass = AST_FORMAT_SLINEAR;
|
||||
p->fr.timelen = 30;
|
||||
p->fr.data = p->obuf;
|
||||
p->fr.datalen = p->obuflen;
|
||||
p->fr.mallocd = 0;
|
||||
p->fr.offset = AST_FRIENDLY_OFFSET;
|
||||
p->fr.src = __FUNCTION__;
|
||||
p->obuflen = 0;
|
||||
return &p->fr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int i4l_write(struct ast_modem_pvt *p, struct ast_frame *f)
|
||||
{
|
||||
#define MAX_WRITE_SIZE 512
|
||||
unsigned char result[MAX_WRITE_SIZE << 1];
|
||||
unsigned char b;
|
||||
int bpos=0, x;
|
||||
int res;
|
||||
if (f->datalen > MAX_WRITE_SIZE) {
|
||||
ast_log(LOG_WARNING, "Discarding too big frame of size %d\n", f->datalen);
|
||||
return -1;
|
||||
}
|
||||
if (f->frametype != AST_FRAME_VOICE) {
|
||||
ast_log(LOG_WARNING, "Don't know how to handle %d type frames\n", f->frametype);
|
||||
return -1;
|
||||
}
|
||||
if (f->subclass != AST_FORMAT_SLINEAR) {
|
||||
ast_log(LOG_WARNING, "Don't know how to handle anything but signed linear frames\n");
|
||||
return -1;
|
||||
}
|
||||
for (x=0;x<f->datalen/2;x++) {
|
||||
b = INT2ALAW(((short *)f->data)[x]);
|
||||
result[bpos++] = b;
|
||||
if (b == CHAR_DLE)
|
||||
result[bpos++]=b;
|
||||
}
|
||||
#if 0
|
||||
res = fwrite(result, bpos, 1, p->f);
|
||||
res *= bpos;
|
||||
#else
|
||||
res = write(p->fd, result, bpos);
|
||||
#endif
|
||||
if (res < 1) {
|
||||
ast_log(LOG_WARNING, "Failed to write buffer\n");
|
||||
return -1;
|
||||
}
|
||||
#if 0
|
||||
printf("Result of write is %d\n", res);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *i4l_identify(struct ast_modem_pvt *p)
|
||||
{
|
||||
return strdup("Linux ISDN");
|
||||
}
|
||||
|
||||
static void i4l_incusecnt()
|
||||
{
|
||||
ast_pthread_mutex_lock(&usecnt_lock);
|
||||
usecnt++;
|
||||
ast_pthread_mutex_unlock(&usecnt_lock);
|
||||
ast_update_use_count();
|
||||
}
|
||||
|
||||
static void i4l_decusecnt()
|
||||
{
|
||||
ast_pthread_mutex_lock(&usecnt_lock);
|
||||
usecnt++;
|
||||
ast_pthread_mutex_unlock(&usecnt_lock);
|
||||
ast_update_use_count();
|
||||
}
|
||||
|
||||
static int i4l_answer(struct ast_modem_pvt *p)
|
||||
{
|
||||
if (ast_modem_send(p, "ATA", 0) ||
|
||||
ast_modem_expect(p, "VCON", 10)) {
|
||||
ast_log(LOG_WARNING, "Unable to answer: %s", p->response);
|
||||
return -1;
|
||||
}
|
||||
#if 1
|
||||
if (ast_modem_send(p, "AT+VDD=0,8", 0) ||
|
||||
ast_modem_expect(p, "OK", 5)) {
|
||||
ast_log(LOG_WARNING, "Unable to set to phone line interface\n");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
if (ast_modem_send(p, "AT+VTX+VRX", 0) ||
|
||||
ast_modem_expect(p, "CONNECT", 10)) {
|
||||
ast_log(LOG_WARNING, "Unable to answer: %s", p->response);
|
||||
return -1;
|
||||
}
|
||||
p->ministate = STATE_VOICE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i4l_dialdigit(struct ast_modem_pvt *p, char digit)
|
||||
{
|
||||
char c[2];
|
||||
if (p->ministate == STATE_VOICE) {
|
||||
c[0] = CHAR_DLE;
|
||||
c[1] = digit;
|
||||
write(p->fd, c, 2);
|
||||
} else
|
||||
ast_log(LOG_DEBUG, "Asked to send digit but call not up on %s\n", p->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i4l_dial(struct ast_modem_pvt *p, char *stuff)
|
||||
{
|
||||
char cmd[80];
|
||||
snprintf(cmd, sizeof(cmd), "ATD%c %s\n", p->dialtype,stuff);
|
||||
if (ast_modem_send(p, cmd, strlen(cmd))) {
|
||||
ast_log(LOG_WARNING, "Unable to dial\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i4l_hangup(struct ast_modem_pvt *p)
|
||||
{
|
||||
char dummy[50];
|
||||
sprintf(dummy, "%c%c", 0x10, 0x3);
|
||||
if (write(p->fd, dummy, 2) < 0) {
|
||||
ast_log(LOG_WARNING, "Failed to break\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read anything outstanding */
|
||||
while(read(p->fd, dummy, sizeof(dummy)) > 0);
|
||||
|
||||
sprintf(dummy, "%c%c", 0x10, 0x14);
|
||||
if (write(p->fd, dummy, 2) < 0) {
|
||||
ast_log(LOG_WARNING, "Failed to break\n");
|
||||
return -1;
|
||||
}
|
||||
ast_modem_expect(p, "VCON", 1);
|
||||
#if 0
|
||||
if (ast_modem_expect(p, "VCON", 8)) {
|
||||
ast_log(LOG_WARNING, "Didn't get expected VCON\n");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
write(p->fd, "\n\n", 2);
|
||||
read(p->fd, dummy, sizeof(dummy));
|
||||
/* Hangup by switching to data, then back to voice */
|
||||
if (ast_modem_send(p, "ATH", 0) ||
|
||||
ast_modem_expect(p, "NO CARRIER", 8)) {
|
||||
ast_log(LOG_WARNING, "Unable to hang up\n");
|
||||
return -1;
|
||||
}
|
||||
if (ast_modem_expect(p, "OK", 5)) {
|
||||
ast_log(LOG_WARNING, "Final 'OK' not received\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ast_modem_driver i4l_driver =
|
||||
{
|
||||
"i4l",
|
||||
i4l_idents,
|
||||
AST_FORMAT_SLINEAR,
|
||||
0, /* Not full duplex */
|
||||
i4l_incusecnt, /* incusecnt */
|
||||
i4l_decusecnt, /* decusecnt */
|
||||
i4l_identify, /* identify */
|
||||
i4l_init, /* init */
|
||||
i4l_setdev, /* setdev */
|
||||
i4l_read,
|
||||
i4l_write,
|
||||
i4l_dial, /* dial */
|
||||
i4l_answer, /* answer */
|
||||
i4l_hangup, /* hangup */
|
||||
i4l_startrec, /* start record */
|
||||
NULL, /* stop record */
|
||||
NULL, /* start playback */
|
||||
NULL, /* stop playback */
|
||||
NULL, /* set silence supression */
|
||||
i4l_dialdigit, /* dialdigit */
|
||||
};
|
||||
|
||||
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
ast_pthread_mutex_lock(&usecnt_lock);
|
||||
res = usecnt;
|
||||
ast_pthread_mutex_unlock(&usecnt_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_modem_driver(&i4l_driver);
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
return ast_unregister_modem_driver(&i4l_driver);
|
||||
}
|
||||
|
||||
char *description()
|
||||
{
|
||||
return desc;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
@@ -33,10 +33,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <linux/soundcard.h>
|
||||
#include "busy.h"
|
||||
#include "ringtone.h"
|
||||
#include "ring10.h"
|
||||
#include "answer.h"
|
||||
|
||||
/* Which device to use */
|
||||
#define DEV_DSP "/dev/dsp"
|
||||
@@ -47,7 +43,7 @@
|
||||
/* When you set the frame size, you have to come up with
|
||||
the right buffer format as well. */
|
||||
/* 5 64-byte frames = one frame */
|
||||
#define BUFFER_FMT ((buffersize * 10) << 16) | (0x0006);
|
||||
#define BUFFER_FMT ((buffersize * 5) << 16) | (0x0006);
|
||||
|
||||
/* Don't switch between read/write modes faster than every 300 ms */
|
||||
#define MIN_SWITCH_TIME 600
|
||||
@@ -56,7 +52,6 @@ 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;
|
||||
@@ -75,32 +70,10 @@ 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, };
|
||||
|
||||
struct sound {
|
||||
int ind;
|
||||
short *data;
|
||||
int datalen;
|
||||
int samplen;
|
||||
int silencelen;
|
||||
int repeat;
|
||||
};
|
||||
|
||||
static struct sound sounds[] = {
|
||||
{ AST_CONTROL_RINGING, ringtone, sizeof(ringtone)/2, 16000, 32000, 1 },
|
||||
{ AST_CONTROL_BUSY, busy, sizeof(busy)/2, 4000, 4000, 1 },
|
||||
{ AST_CONTROL_CONGESTION, busy, sizeof(busy)/2, 2000, 2000, 1 },
|
||||
{ AST_CONTROL_RING, ring10, sizeof(ring10)/2, 16000, 32000, 1 },
|
||||
{ AST_CONTROL_ANSWER, answer, sizeof(answer)/2, 2200, 0, 0 },
|
||||
};
|
||||
|
||||
/* Sound command pipe */
|
||||
static int sndcmd[2];
|
||||
/* Some pipes to prevent overflow */
|
||||
static int funnel[2];
|
||||
static pthread_mutex_t sound_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_t silly;
|
||||
|
||||
static struct chan_oss_pvt {
|
||||
/* We only have one OSS structure -- near sighted perhaps, but it
|
||||
@@ -126,7 +99,6 @@ static int time_has_passed()
|
||||
with 160 sample frames, and a buffer size of 3, we have a 60ms buffer,
|
||||
usually plenty. */
|
||||
|
||||
pthread_t sthread;
|
||||
|
||||
#define MAX_BUFFER_SIZE 100
|
||||
static int buffersize = 3;
|
||||
@@ -155,108 +127,6 @@ static int calc_loudness(short *frame)
|
||||
return sum;
|
||||
}
|
||||
|
||||
static int cursound = -1;
|
||||
static int sampsent = 0;
|
||||
static int silencelen=0;
|
||||
static int offset=0;
|
||||
static int nosound=0;
|
||||
|
||||
static int send_sound(void)
|
||||
{
|
||||
short myframe[FRAME_SIZE];
|
||||
int total = FRAME_SIZE;
|
||||
short *frame = NULL;
|
||||
int amt=0;
|
||||
int res;
|
||||
int myoff;
|
||||
audio_buf_info abi;
|
||||
if (cursound > -1) {
|
||||
res = ioctl(sounddev, SNDCTL_DSP_GETOSPACE ,&abi);
|
||||
if (res) {
|
||||
ast_log(LOG_WARNING, "Unable to read output space\n");
|
||||
return -1;
|
||||
}
|
||||
/* Calculate how many samples we can send, max */
|
||||
if (total > (abi.fragments * abi.fragsize / 2))
|
||||
total = abi.fragments * abi.fragsize / 2;
|
||||
res = total;
|
||||
if (sampsent < sounds[cursound].samplen) {
|
||||
myoff=0;
|
||||
while(total) {
|
||||
amt = total;
|
||||
if (amt > (sounds[cursound].datalen - offset))
|
||||
amt = sounds[cursound].datalen - offset;
|
||||
memcpy(myframe + myoff, sounds[cursound].data + offset, amt * 2);
|
||||
total -= amt;
|
||||
offset += amt;
|
||||
sampsent += amt;
|
||||
myoff += amt;
|
||||
if (offset >= sounds[cursound].datalen)
|
||||
offset = 0;
|
||||
}
|
||||
/* Set it up for silence */
|
||||
if (sampsent >= sounds[cursound].samplen)
|
||||
silencelen = sounds[cursound].silencelen;
|
||||
frame = myframe;
|
||||
} else {
|
||||
if (silencelen > 0) {
|
||||
frame = silence;
|
||||
silencelen -= res;
|
||||
} else {
|
||||
if (sounds[cursound].repeat) {
|
||||
/* Start over */
|
||||
sampsent = 0;
|
||||
offset = 0;
|
||||
} else {
|
||||
cursound = -1;
|
||||
nosound = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
res = write(sounddev, frame, res * 2);
|
||||
if (res > 0)
|
||||
return 0;
|
||||
return res;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *sound_thread(void *unused)
|
||||
{
|
||||
fd_set rfds;
|
||||
fd_set wfds;
|
||||
int max;
|
||||
int res;
|
||||
for(;;) {
|
||||
FD_ZERO(&rfds);
|
||||
FD_ZERO(&wfds);
|
||||
max = sndcmd[0];
|
||||
FD_SET(sndcmd[0], &rfds);
|
||||
if (cursound > -1) {
|
||||
FD_SET(sounddev, &wfds);
|
||||
if (sounddev > max)
|
||||
max = sounddev;
|
||||
}
|
||||
res = select(max + 1, &rfds, &wfds, NULL, NULL);
|
||||
if (res < 1) {
|
||||
ast_log(LOG_WARNING, "select failed: %s\n", strerror(errno));
|
||||
continue;
|
||||
}
|
||||
if (FD_ISSET(sndcmd[0], &rfds)) {
|
||||
read(sndcmd[0], &cursound, sizeof(cursound));
|
||||
silencelen = 0;
|
||||
offset = 0;
|
||||
sampsent = 0;
|
||||
}
|
||||
if (FD_ISSET(sounddev, &wfds))
|
||||
if (send_sound())
|
||||
ast_log(LOG_WARNING, "Failed to write sound\n");
|
||||
}
|
||||
/* Never reached */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int silence_suppress(short *buf)
|
||||
{
|
||||
#define SILBUF 3
|
||||
@@ -289,23 +159,57 @@ static int silence_suppress(short *buf)
|
||||
/* Write any buffered silence we have, it may have something
|
||||
important */
|
||||
if (silbufcnt) {
|
||||
write(sounddev, silbuf, silbufcnt * FRAME_SIZE);
|
||||
write(funnel[1], silbuf, silbufcnt * FRAME_SIZE);
|
||||
silbufcnt = 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void *silly_thread(void *ignore)
|
||||
{
|
||||
char buf[FRAME_SIZE * 2];
|
||||
int pos=0;
|
||||
int res=0;
|
||||
/* Read from the sound device, and write to the pipe. */
|
||||
for (;;) {
|
||||
/* Give the writer a better shot at the lock */
|
||||
#if 0
|
||||
usleep(1000);
|
||||
#endif
|
||||
pthread_testcancel();
|
||||
pthread_mutex_lock(&sound_lock);
|
||||
res = read(sounddev, buf + pos, FRAME_SIZE * 2 - pos);
|
||||
pthread_mutex_unlock(&sound_lock);
|
||||
if (res > 0) {
|
||||
pos += res;
|
||||
if (pos == FRAME_SIZE * 2) {
|
||||
if (needhangup || needanswer || strlen(digits) ||
|
||||
!silence_suppress((short *)buf)) {
|
||||
res = write(funnel[1], buf, sizeof(buf));
|
||||
}
|
||||
pos = 0;
|
||||
}
|
||||
} else {
|
||||
close(funnel[1]);
|
||||
break;
|
||||
}
|
||||
pthread_testcancel();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int setformat(void)
|
||||
{
|
||||
int fmt, desired, res, fd = sounddev;
|
||||
static int warnedalready = 0;
|
||||
static int warnedalready2 = 0;
|
||||
pthread_mutex_lock(&sound_lock);
|
||||
fmt = AFMT_S16_LE;
|
||||
res = ioctl(fd, SNDCTL_DSP_SETFMT, &fmt);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to set format to 16-bit signed\n");
|
||||
pthread_mutex_unlock(&sound_lock);
|
||||
return -1;
|
||||
}
|
||||
res = ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0);
|
||||
@@ -318,6 +222,7 @@ static int setformat(void)
|
||||
res = ioctl(fd, SNDCTL_DSP_STEREO, &fmt);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Failed to set audio device to mono\n");
|
||||
pthread_mutex_unlock(&sound_lock);
|
||||
return -1;
|
||||
}
|
||||
/* 8000 Hz desired */
|
||||
@@ -326,6 +231,7 @@ static int setformat(void)
|
||||
res = ioctl(fd, SNDCTL_DSP_SPEED, &fmt);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Failed to set audio device to mono\n");
|
||||
pthread_mutex_unlock(&sound_lock);
|
||||
return -1;
|
||||
}
|
||||
if (fmt != desired) {
|
||||
@@ -340,6 +246,7 @@ static int setformat(void)
|
||||
ast_log(LOG_WARNING, "Unable to set fragment size -- sound may be choppy\n");
|
||||
}
|
||||
#endif
|
||||
pthread_mutex_unlock(&sound_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -349,6 +256,7 @@ static int soundcard_setoutput(int force)
|
||||
int fd = sounddev;
|
||||
if (full_duplex || (!readmode && !force))
|
||||
return 0;
|
||||
pthread_mutex_lock(&sound_lock);
|
||||
readmode = 0;
|
||||
if (force || time_has_passed()) {
|
||||
ioctl(sounddev, SNDCTL_DSP_RESET);
|
||||
@@ -356,21 +264,26 @@ static int soundcard_setoutput(int force)
|
||||
time. */
|
||||
/* dup2(0, sound); */
|
||||
close(sounddev);
|
||||
fd = open(DEV_DSP, O_WRONLY |O_NONBLOCK);
|
||||
fd = open(DEV_DSP, O_WRONLY);
|
||||
if (fd < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to re-open DSP device: %s\n", strerror(errno));
|
||||
pthread_mutex_unlock(&sound_lock);
|
||||
return -1;
|
||||
}
|
||||
/* dup2 will close the original and make fd be sound */
|
||||
if (dup2(fd, sounddev) < 0) {
|
||||
ast_log(LOG_WARNING, "dup2() failed: %s\n", strerror(errno));
|
||||
pthread_mutex_unlock(&sound_lock);
|
||||
return -1;
|
||||
}
|
||||
if (setformat()) {
|
||||
pthread_mutex_unlock(&sound_lock);
|
||||
return -1;
|
||||
}
|
||||
pthread_mutex_unlock(&sound_lock);
|
||||
return 0;
|
||||
}
|
||||
pthread_mutex_unlock(&sound_lock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -379,35 +292,41 @@ static int soundcard_setinput(int force)
|
||||
int fd = sounddev;
|
||||
if (full_duplex || (readmode && !force))
|
||||
return 0;
|
||||
pthread_mutex_lock(&sound_lock);
|
||||
readmode = -1;
|
||||
if (force || time_has_passed()) {
|
||||
ioctl(sounddev, SNDCTL_DSP_RESET);
|
||||
close(sounddev);
|
||||
/* dup2(0, sound); */
|
||||
fd = open(DEV_DSP, O_RDONLY | O_NONBLOCK);
|
||||
fd = open(DEV_DSP, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to re-open DSP device: %s\n", strerror(errno));
|
||||
pthread_mutex_unlock(&sound_lock);
|
||||
return -1;
|
||||
}
|
||||
/* dup2 will close the original and make fd be sound */
|
||||
if (dup2(fd, sounddev) < 0) {
|
||||
ast_log(LOG_WARNING, "dup2() failed: %s\n", strerror(errno));
|
||||
pthread_mutex_unlock(&sound_lock);
|
||||
return -1;
|
||||
}
|
||||
if (setformat()) {
|
||||
pthread_mutex_unlock(&sound_lock);
|
||||
return -1;
|
||||
}
|
||||
pthread_mutex_unlock(&sound_lock);
|
||||
return 0;
|
||||
}
|
||||
pthread_mutex_unlock(&sound_lock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int soundcard_init()
|
||||
{
|
||||
/* Assume it's full duplex for starters */
|
||||
int fd = open(DEV_DSP, O_RDWR | O_NONBLOCK);
|
||||
int fd = open(DEV_DSP, O_RDWR);
|
||||
if (fd < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to open %s: %s\n", DEV_DSP, strerror(errno));
|
||||
ast_log(LOG_ERROR, "Unable to open %s: %s\n", DEV_DSP, strerror(errno));
|
||||
return fd;
|
||||
}
|
||||
gettimeofday(&lasttime, NULL);
|
||||
@@ -432,53 +351,33 @@ 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;
|
||||
ast_verbose( " << Call placed to '%s' on console >> \n", dest);
|
||||
if (autoanswer) {
|
||||
ast_verbose( " << Auto-answered >> \n" );
|
||||
needanswer = 1;
|
||||
} else {
|
||||
ast_verbose( " << Type 'answer' to answer, or use 'autoanswer' for future calls >> \n");
|
||||
needringing = 1;
|
||||
write(sndcmd[1], &res, sizeof(res));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void answer_sound(void)
|
||||
{
|
||||
int res;
|
||||
nosound = 1;
|
||||
res = 4;
|
||||
write(sndcmd[1], &res, sizeof(res));
|
||||
|
||||
}
|
||||
|
||||
static int oss_answer(struct ast_channel *c)
|
||||
{
|
||||
ast_verbose( " << Console call has been answered >> \n");
|
||||
answer_sound();
|
||||
c->state = AST_STATE_UP;
|
||||
cursound = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int oss_hangup(struct ast_channel *c)
|
||||
{
|
||||
int res;
|
||||
cursound = -1;
|
||||
c->pvt->pvt = NULL;
|
||||
oss.owner = NULL;
|
||||
ast_verbose( " << Hangup on console >> \n");
|
||||
ast_pthread_mutex_lock(&usecnt_lock);
|
||||
pthread_mutex_lock(&usecnt_lock);
|
||||
usecnt--;
|
||||
ast_pthread_mutex_unlock(&usecnt_lock);
|
||||
pthread_mutex_unlock(&usecnt_lock);
|
||||
needhangup = 0;
|
||||
needanswer = 0;
|
||||
if (hookstate) {
|
||||
res = 2;
|
||||
write(sndcmd[1], &res, sizeof(res));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -486,11 +385,12 @@ static int soundcard_writeframe(short *data)
|
||||
{
|
||||
/* Write an exactly FRAME_SIZE sized of frame */
|
||||
static int bufcnt = 0;
|
||||
static short buffer[FRAME_SIZE * MAX_BUFFER_SIZE * 5];
|
||||
static char buffer[FRAME_SIZE * 2 * MAX_BUFFER_SIZE * 5];
|
||||
struct audio_buf_info info;
|
||||
int res;
|
||||
int fd = sounddev;
|
||||
static int warned=0;
|
||||
pthread_mutex_lock(&sound_lock);
|
||||
if (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info)) {
|
||||
if (!warned)
|
||||
ast_log(LOG_WARNING, "Error reading output space\n");
|
||||
@@ -507,12 +407,13 @@ static int soundcard_writeframe(short *data)
|
||||
} else {
|
||||
/* Copy the data into our buffer */
|
||||
res = FRAME_SIZE * 2;
|
||||
memcpy(buffer + (bufcnt * FRAME_SIZE), data, FRAME_SIZE * 2);
|
||||
memcpy(buffer + (bufcnt * FRAME_SIZE * 2), data, FRAME_SIZE * 2);
|
||||
bufcnt++;
|
||||
if (bufcnt == buffersize) {
|
||||
res = write(fd, ((void *)buffer), FRAME_SIZE * 2 * buffersize);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&sound_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -524,11 +425,6 @@ static int oss_write(struct ast_channel *chan, struct ast_frame *f)
|
||||
static int sizpos = 0;
|
||||
int len = sizpos;
|
||||
int pos;
|
||||
/* Immediately return if no sound is enabled */
|
||||
if (nosound)
|
||||
return 0;
|
||||
/* Stop any currently playing sound */
|
||||
cursound = -1;
|
||||
if (!full_duplex && (strlen(digits) || needhangup || needanswer)) {
|
||||
/* If we're half duplex, we have to switch to read mode
|
||||
to honor immediate needs if necessary */
|
||||
@@ -572,18 +468,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,15 +482,7 @@ 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)) {
|
||||
@@ -628,9 +509,6 @@ static struct ast_frame *oss_read(struct ast_channel *chan)
|
||||
return &f;
|
||||
}
|
||||
|
||||
if (nonull)
|
||||
return &f;
|
||||
|
||||
res = soundcard_setinput(0);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to set input mode\n");
|
||||
@@ -640,23 +518,16 @@ static struct ast_frame *oss_read(struct ast_channel *chan)
|
||||
/* Theoretically shouldn't happen, but anyway, return a NULL frame */
|
||||
return &f;
|
||||
}
|
||||
res = read(sounddev, buf + AST_FRIENDLY_OFFSET + readpos, FRAME_SIZE * 2 - readpos);
|
||||
res = read(funnel[0], buf + AST_FRIENDLY_OFFSET + readpos, FRAME_SIZE * 2 - readpos);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Error reading from sound device (If you're running 'artsd' then kill it): %s\n", strerror(errno));
|
||||
#if 0
|
||||
CRASH;
|
||||
#endif
|
||||
ast_log(LOG_WARNING, "Error reading from sound device: %s\n", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
readpos += res;
|
||||
|
||||
if (readpos >= FRAME_SIZE * 2) {
|
||||
if (readpos == FRAME_SIZE * 2) {
|
||||
/* A real frame */
|
||||
readpos = 0;
|
||||
if (chan->state != AST_STATE_UP) {
|
||||
/* Don't transmit unless it's up */
|
||||
return &f;
|
||||
}
|
||||
f.frametype = AST_FRAME_VOICE;
|
||||
f.subclass = AST_FORMAT_SLINEAR;
|
||||
f.timelen = FRAME_SIZE / 8;
|
||||
@@ -665,47 +536,10 @@ static struct ast_frame *oss_read(struct ast_channel *chan)
|
||||
f.offset = AST_FRIENDLY_OFFSET;
|
||||
f.src = type;
|
||||
f.mallocd = 0;
|
||||
#if 0
|
||||
{ static int fd = -1;
|
||||
if (fd < 0)
|
||||
fd = open("output.raw", O_RDWR | O_TRUNC | O_CREAT);
|
||||
write(fd, f.data, f.datalen);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return &f;
|
||||
}
|
||||
|
||||
static int oss_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
|
||||
{
|
||||
struct chan_oss_pvt *p = newchan->pvt->pvt;
|
||||
p->owner = newchan;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int oss_indicate(struct ast_channel *chan, int cond)
|
||||
{
|
||||
int res;
|
||||
switch(cond) {
|
||||
case AST_CONTROL_BUSY:
|
||||
res = 1;
|
||||
break;
|
||||
case AST_CONTROL_CONGESTION:
|
||||
res = 2;
|
||||
break;
|
||||
case AST_CONTROL_RINGING:
|
||||
res = 0;
|
||||
break;
|
||||
default:
|
||||
ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, chan->name);
|
||||
return -1;
|
||||
}
|
||||
if (res > -1) {
|
||||
write(sndcmd[1], &res, sizeof(res));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ast_channel *oss_new(struct chan_oss_pvt *p, int state)
|
||||
{
|
||||
struct ast_channel *tmp;
|
||||
@@ -713,9 +547,8 @@ static struct ast_channel *oss_new(struct chan_oss_pvt *p, int state)
|
||||
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->fd = funnel[0];
|
||||
tmp->format = AST_FORMAT_SLINEAR;
|
||||
tmp->pvt->pvt = p;
|
||||
tmp->pvt->send_digit = oss_digit;
|
||||
tmp->pvt->send_text = oss_text;
|
||||
@@ -724,8 +557,6 @@ static struct ast_channel *oss_new(struct chan_oss_pvt *p, int state)
|
||||
tmp->pvt->read = oss_read;
|
||||
tmp->pvt->call = oss_call;
|
||||
tmp->pvt->write = oss_write;
|
||||
tmp->pvt->indicate = oss_indicate;
|
||||
tmp->pvt->fixup = oss_fixup;
|
||||
if (strlen(p->context))
|
||||
strncpy(tmp->context, p->context, sizeof(tmp->context));
|
||||
if (strlen(p->exten))
|
||||
@@ -734,9 +565,9 @@ static struct ast_channel *oss_new(struct chan_oss_pvt *p, int state)
|
||||
strncpy(tmp->language, language, sizeof(tmp->language));
|
||||
p->owner = tmp;
|
||||
tmp->state = state;
|
||||
ast_pthread_mutex_lock(&usecnt_lock);
|
||||
pthread_mutex_lock(&usecnt_lock);
|
||||
usecnt++;
|
||||
ast_pthread_mutex_unlock(&usecnt_lock);
|
||||
pthread_mutex_unlock(&usecnt_lock);
|
||||
ast_update_use_count();
|
||||
if (state != AST_STATE_DOWN) {
|
||||
if (ast_pbx_start(tmp)) {
|
||||
@@ -819,10 +650,7 @@ static int console_answer(int fd, int argc, char *argv[])
|
||||
ast_cli(fd, "No one is calling us\n");
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
hookstate = 1;
|
||||
cursound = -1;
|
||||
needanswer++;
|
||||
answer_sound();
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -858,14 +686,11 @@ static int console_hangup(int fd, int argc, char *argv[])
|
||||
{
|
||||
if (argc != 1)
|
||||
return RESULT_SHOWUSAGE;
|
||||
cursound = -1;
|
||||
if (!oss.owner && !hookstate) {
|
||||
if (!oss.owner) {
|
||||
ast_cli(fd, "No call to hangup up\n");
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
hookstate = 0;
|
||||
if (oss.owner)
|
||||
needhangup++;
|
||||
needhangup++;
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -878,15 +703,12 @@ static int console_dial(int fd, int argc, char *argv[])
|
||||
{
|
||||
char tmp[256], *tmp2;
|
||||
char *mye, *myc;
|
||||
int b = 0;
|
||||
if ((argc != 1) && (argc != 2))
|
||||
return RESULT_SHOWUSAGE;
|
||||
if (oss.owner) {
|
||||
if (argc == 2) {
|
||||
if (argc == 2)
|
||||
strncat(digits, argv[1], sizeof(digits) - strlen(digits));
|
||||
/* Wake up the polling thread */
|
||||
write(cmd[1], &b, sizeof(b));
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
@@ -903,10 +725,9 @@ static int console_dial(int fd, int argc, char *argv[])
|
||||
if (tmp2 && strlen(tmp2))
|
||||
myc = tmp2;
|
||||
}
|
||||
if (ast_exists_extension(NULL, myc, mye, 1, NULL)) {
|
||||
if (ast_exists_extension(NULL, myc, mye, 1)) {
|
||||
strncpy(oss.exten, mye, sizeof(oss.exten));
|
||||
strncpy(oss.context, myc, sizeof(oss.context));
|
||||
hookstate = 1;
|
||||
oss_new(&oss, AST_STATE_UP);
|
||||
} else
|
||||
ast_cli(fd, "No such extension '%s' in context '%s'\n", mye, myc);
|
||||
@@ -933,28 +754,28 @@ int load_module()
|
||||
int flags;
|
||||
struct ast_config *cfg = ast_load(config);
|
||||
struct ast_variable *v;
|
||||
res = pipe(cmd);
|
||||
res = pipe(sndcmd);
|
||||
res = pipe(funnel);
|
||||
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);
|
||||
/* We make the funnel so that writes to the funnel don't block...
|
||||
Our "silly" thread can read to its heart content, preventing
|
||||
recording overruns */
|
||||
flags = fcntl(funnel[1], F_GETFL);
|
||||
#if 0
|
||||
fcntl(funnel[0], F_SETFL, flags | O_NONBLOCK);
|
||||
#endif
|
||||
fcntl(funnel[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");
|
||||
}
|
||||
return 0;
|
||||
close(funnel[1]);
|
||||
close(funnel[0]);
|
||||
return -1;
|
||||
}
|
||||
if (!full_duplex)
|
||||
ast_log(LOG_WARNING, "XXX I don't work right with non-full duplex sound cards XXX\n");
|
||||
pthread_create(&silly, NULL, silly_thread, NULL);
|
||||
res = ast_channel_register(type, tdesc, AST_FORMAT_SLINEAR, oss_request);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", type);
|
||||
@@ -981,7 +802,6 @@ int load_module()
|
||||
}
|
||||
ast_destroy(cfg);
|
||||
}
|
||||
pthread_create(&sthread, NULL, sound_thread, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -993,13 +813,13 @@ 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 (funnel[0] > 0) {
|
||||
close(funnel[0]);
|
||||
close(funnel[1]);
|
||||
}
|
||||
if (sndcmd[0] > 0) {
|
||||
close(sndcmd[0]);
|
||||
close(sndcmd[1]);
|
||||
if (silly) {
|
||||
pthread_cancel(silly);
|
||||
pthread_join(silly, NULL);
|
||||
}
|
||||
if (oss.owner)
|
||||
ast_softhangup(oss.owner);
|
||||
@@ -1016,13 +836,8 @@ char *description()
|
||||
int usecount()
|
||||
{
|
||||
int res;
|
||||
ast_pthread_mutex_lock(&usecnt_lock);
|
||||
pthread_mutex_lock(&usecnt_lock);
|
||||
res = usecnt;
|
||||
ast_pthread_mutex_unlock(&usecnt_lock);
|
||||
pthread_mutex_unlock(&usecnt_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
@@ -34,8 +34,7 @@
|
||||
#include <linux/ixjuser.h>
|
||||
#include "DialTone.h"
|
||||
|
||||
#define PHONE_MAX_BUF 480
|
||||
#define DEFAULT_GAIN 0x100
|
||||
#define phone_MAX_BUF 480
|
||||
|
||||
static char *desc = "Linux Telephony API Support";
|
||||
static char *type = "Phone";
|
||||
@@ -53,7 +52,7 @@ static int echocancel = AEC_OFF;
|
||||
|
||||
static int silencesupression = 0;
|
||||
|
||||
static int prefformat = AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW;
|
||||
static int prefformat = AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR;
|
||||
|
||||
static pthread_mutex_t usecnt_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
@@ -75,7 +74,6 @@ static int restart_monitor(void);
|
||||
|
||||
#define MODE_DIALTONE 1
|
||||
#define MODE_IMMEDIATE 2
|
||||
#define MODE_FXO 3
|
||||
|
||||
static struct phone_pvt {
|
||||
int fd; /* Raw file descriptor for this device */
|
||||
@@ -88,22 +86,16 @@ static struct phone_pvt {
|
||||
struct phone_pvt *next; /* Next channel in list */
|
||||
struct ast_frame fr; /* Frame */
|
||||
char offset[AST_FRIENDLY_OFFSET];
|
||||
char buf[PHONE_MAX_BUF]; /* Static buffer for reading frames */
|
||||
char buf[phone_MAX_BUF]; /* Static buffer for reading frames */
|
||||
int obuflen;
|
||||
int dialtone;
|
||||
int txgain, rxgain; /* gain control for playing, recording */
|
||||
/* 0x100 - 1.0, 0x200 - 2.0, 0x80 - 0.5 */
|
||||
int cpt; /* Call Progress Tone playing? */
|
||||
int silencesupression;
|
||||
char context[AST_MAX_EXTENSION];
|
||||
char obuf[PHONE_MAX_BUF * 2];
|
||||
char obuf[phone_MAX_BUF * 2];
|
||||
char ext[AST_MAX_EXTENSION];
|
||||
char language[MAX_LANGUAGE];
|
||||
char callerid[AST_MAX_EXTENSION];
|
||||
} *iflist = NULL;
|
||||
|
||||
static char callerid[AST_MAX_EXTENSION];
|
||||
|
||||
static int phone_digit(struct ast_channel *ast, char digit)
|
||||
{
|
||||
struct phone_pvt *p;
|
||||
@@ -133,7 +125,6 @@ static int phone_digit(struct ast_channel *ast, char digit)
|
||||
return -1;
|
||||
}
|
||||
ioctl(p->fd, PHONE_PLAY_TONE, digit);
|
||||
p->lastformat = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -148,7 +139,7 @@ static int phone_call(struct ast_channel *ast, char *dest, int timeout)
|
||||
/* When we call, it just works, really, there's no destination... Just
|
||||
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]);
|
||||
ast_log(LOG_DEBUG, "Ringing %s on %s (%d)\n", dest, ast->name, ast->fd);
|
||||
ioctl(p->fd, PHONE_RING_START);
|
||||
ast->state = AST_STATE_RINGING;
|
||||
return 0;
|
||||
@@ -174,19 +165,11 @@ static int phone_hangup(struct ast_channel *ast)
|
||||
ast_log(LOG_WARNING, "Failed to stop ringing\n");
|
||||
if (ioctl(p->fd, PHONE_CPT_STOP))
|
||||
ast_log(LOG_WARNING, "Failed to stop sounds\n");
|
||||
|
||||
/* If it's an FXO, hang them up */
|
||||
if (p->mode == MODE_FXO) {
|
||||
if (ioctl(p->fd, PHONE_PSTN_SET_STATE, PSTN_ON_HOOK))
|
||||
ast_log(LOG_DEBUG, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n",ast->name, strerror(errno));
|
||||
}
|
||||
|
||||
/* If they're off hook, give a busy signal */
|
||||
if (ioctl(p->fd, PHONE_HOOKSTATE)) {
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "Got hunghup, giving busy signal\n");
|
||||
ioctl(p->fd, PHONE_BUSY);
|
||||
p->cpt = 1;
|
||||
}
|
||||
p->lastformat = -1;
|
||||
p->lastinput = -1;
|
||||
@@ -195,11 +178,11 @@ static int phone_hangup(struct ast_channel *ast)
|
||||
p->dialtone = 0;
|
||||
memset(p->ext, 0, sizeof(p->ext));
|
||||
((struct phone_pvt *)(ast->pvt->pvt))->owner = NULL;
|
||||
ast_pthread_mutex_lock(&usecnt_lock);
|
||||
pthread_mutex_lock(&usecnt_lock);
|
||||
usecnt--;
|
||||
if (usecnt < 0)
|
||||
ast_log(LOG_WARNING, "Usecnt < 0???\n");
|
||||
ast_pthread_mutex_unlock(&usecnt_lock);
|
||||
pthread_mutex_unlock(&usecnt_lock);
|
||||
ast_update_use_count();
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
|
||||
@@ -215,7 +198,7 @@ static int phone_setup(struct ast_channel *ast)
|
||||
p = ast->pvt->pvt;
|
||||
ioctl(p->fd, PHONE_CPT_STOP);
|
||||
/* Nothing to answering really, just start recording */
|
||||
if (ast->pvt->rawreadformat == AST_FORMAT_G723_1) {
|
||||
if (ast->format & AST_FORMAT_G723_1) {
|
||||
/* Prefer g723 */
|
||||
ioctl(p->fd, PHONE_REC_STOP);
|
||||
if (p->lastinput != AST_FORMAT_G723_1) {
|
||||
@@ -225,7 +208,7 @@ static int phone_setup(struct ast_channel *ast)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} else if (ast->pvt->rawreadformat == AST_FORMAT_SLINEAR) {
|
||||
} else if (ast->format & AST_FORMAT_SLINEAR) {
|
||||
ioctl(p->fd, PHONE_REC_STOP);
|
||||
if (p->lastinput != AST_FORMAT_SLINEAR) {
|
||||
p->lastinput = AST_FORMAT_SLINEAR;
|
||||
@@ -234,17 +217,8 @@ static int phone_setup(struct ast_channel *ast)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} else if (ast->pvt->rawreadformat == AST_FORMAT_ULAW) {
|
||||
ioctl(p->fd, PHONE_REC_STOP);
|
||||
if (p->lastinput != AST_FORMAT_ULAW) {
|
||||
p->lastinput = AST_FORMAT_ULAW;
|
||||
if (ioctl(p->fd, PHONE_REC_CODEC, ULAW)) {
|
||||
ast_log(LOG_WARNING, "Failed to set codec to signed linear 16\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Can't do format %d\n", ast->pvt->rawreadformat);
|
||||
ast_log(LOG_WARNING, "Can't do format %d\n", ast->format);
|
||||
return -1;
|
||||
}
|
||||
if (ioctl(p->fd, PHONE_REC_START)) {
|
||||
@@ -256,15 +230,6 @@ static int phone_setup(struct ast_channel *ast)
|
||||
|
||||
static int phone_answer(struct ast_channel *ast)
|
||||
{
|
||||
struct phone_pvt *p;
|
||||
p = ast->pvt->pvt;
|
||||
/* In case it's a LineJack, take it off hook */
|
||||
if (p->mode == MODE_FXO) {
|
||||
if (ioctl(p->fd, PHONE_PSTN_SET_STATE, PSTN_OFF_HOOK))
|
||||
ast_log(LOG_DEBUG, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n", ast->name, strerror(errno));
|
||||
else
|
||||
ast_log(LOG_DEBUG, "Took linejack off hook\n");
|
||||
}
|
||||
phone_setup(ast);
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "phone_answer(%s)\n", ast->name);
|
||||
@@ -285,7 +250,7 @@ static char phone_2digit(char c)
|
||||
return '?';
|
||||
}
|
||||
|
||||
static struct ast_frame *phone_exception(struct ast_channel *ast)
|
||||
static struct ast_frame *phone_read(struct ast_channel *ast)
|
||||
{
|
||||
int res;
|
||||
union telephony_exception phonee;
|
||||
@@ -302,9 +267,6 @@ static struct ast_frame *phone_exception(struct ast_channel *ast)
|
||||
|
||||
phonee.bytes = ioctl(p->fd, PHONE_EXCEPTION);
|
||||
if (phonee.bits.dtmf_ready) {
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "phone_exception(): DTMF\n");
|
||||
|
||||
/* We've got a digit -- Just handle this nicely and easily */
|
||||
digit = ioctl(p->fd, PHONE_GET_DTMF_ASCII);
|
||||
p->fr.subclass = digit;
|
||||
@@ -312,13 +274,9 @@ static struct ast_frame *phone_exception(struct ast_channel *ast)
|
||||
return &p->fr;
|
||||
}
|
||||
if (phonee.bits.hookstate) {
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "Hookstate changed\n");
|
||||
res = ioctl(p->fd, PHONE_HOOKSTATE);
|
||||
/* See if we've gone on hook, if so, notify by returning NULL */
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "New hookstate: %d\n", res);
|
||||
if (!res && (p->mode != MODE_FXO))
|
||||
if (!res)
|
||||
return NULL;
|
||||
else {
|
||||
if (ast->state == AST_STATE_RINGING) {
|
||||
@@ -332,37 +290,16 @@ static struct ast_frame *phone_exception(struct ast_channel *ast)
|
||||
ast_log(LOG_WARNING, "Got off hook in weird state %d\n", ast->state);
|
||||
}
|
||||
}
|
||||
#if 1
|
||||
#if 0
|
||||
if (phonee.bits.pstn_ring)
|
||||
ast_verbose("Unit is ringing\n");
|
||||
if (phonee.bits.caller_id) {
|
||||
ast_verbose("We have caller ID: %s\n");
|
||||
}
|
||||
if (phonee.bits.pstn_wink)
|
||||
ast_verbose("Detected Wink\n");
|
||||
#endif
|
||||
/* Strange -- nothing there.. */
|
||||
p->fr.frametype = AST_FRAME_NULL;
|
||||
p->fr.subclass = 0;
|
||||
return &p->fr;
|
||||
}
|
||||
|
||||
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;
|
||||
p->fr.timelen = 0;
|
||||
p->fr.data = NULL;
|
||||
p->fr.src = type;
|
||||
p->fr.offset = 0;
|
||||
p->fr.mallocd=0;
|
||||
|
||||
/* Try to read some data... */
|
||||
CHECK_BLOCKING(ast);
|
||||
res = read(p->fd, p->buf, PHONE_MAX_BUF);
|
||||
res = read(p->fd, p->buf, phone_MAX_BUF);
|
||||
ast->blocking = 0;
|
||||
if (res < 0) {
|
||||
#if 0
|
||||
@@ -414,16 +351,8 @@ static int phone_write_buf(struct phone_pvt *p, char *buf, int len, int frlen)
|
||||
#endif
|
||||
if (res != frlen) {
|
||||
if (res < 1) {
|
||||
/*
|
||||
* 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
|
||||
ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno));
|
||||
return -1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Only wrote %d of %d bytes\n", res, frlen);
|
||||
}
|
||||
@@ -444,7 +373,6 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame)
|
||||
char *pos;
|
||||
int sofar;
|
||||
int expected;
|
||||
int codecset = 0;
|
||||
char tmpbuf[4];
|
||||
/* Write a frame of (presumably voice) data */
|
||||
if (frame->frametype != AST_FRAME_VOICE) {
|
||||
@@ -452,8 +380,7 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame)
|
||||
ast_frfree(frame);
|
||||
return -1;
|
||||
}
|
||||
if (!(frame->subclass &
|
||||
(AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW))) {
|
||||
if (!(frame->subclass & (AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR))) {
|
||||
ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
|
||||
ast_frfree(frame);
|
||||
return -1;
|
||||
@@ -479,7 +406,6 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame)
|
||||
p->lastinput = AST_FORMAT_G723_1;
|
||||
/* Reset output buffer */
|
||||
p->obuflen = 0;
|
||||
codecset = 1;
|
||||
}
|
||||
if (frame->datalen > 24) {
|
||||
ast_log(LOG_WARNING, "Frame size too large for G.723.1 (%d bytes)\n", frame->datalen);
|
||||
@@ -500,42 +426,20 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame)
|
||||
}
|
||||
p->lastformat = AST_FORMAT_SLINEAR;
|
||||
p->lastinput = AST_FORMAT_SLINEAR;
|
||||
codecset = 1;
|
||||
/* Reset output buffer */
|
||||
p->obuflen = 0;
|
||||
}
|
||||
maxfr = 480;
|
||||
} else if (frame->subclass == AST_FORMAT_ULAW) {
|
||||
if (p->lastformat != AST_FORMAT_ULAW) {
|
||||
ioctl(p->fd, PHONE_PLAY_STOP);
|
||||
ioctl(p->fd, PHONE_REC_STOP);
|
||||
if (ioctl(p->fd, PHONE_PLAY_CODEC, ULAW)) {
|
||||
ast_log(LOG_WARNING, "Unable to set uLaw mode\n");
|
||||
return -1;
|
||||
}
|
||||
if (ioctl(p->fd, PHONE_REC_CODEC, ULAW)) {
|
||||
ast_log(LOG_WARNING, "Unable to set uLaw mode\n");
|
||||
return -1;
|
||||
}
|
||||
p->lastformat = AST_FORMAT_ULAW;
|
||||
p->lastinput = AST_FORMAT_ULAW;
|
||||
codecset = 1;
|
||||
/* Reset output buffer */
|
||||
p->obuflen = 0;
|
||||
}
|
||||
maxfr = 240;
|
||||
}
|
||||
if (codecset) {
|
||||
ioctl(p->fd, PHONE_REC_DEPTH, 3);
|
||||
ioctl(p->fd, PHONE_PLAY_DEPTH, 3);
|
||||
if (ioctl(p->fd, PHONE_PLAY_START)) {
|
||||
ast_log(LOG_WARNING, "Failed to start playback\n");
|
||||
return -1;
|
||||
}
|
||||
if (ioctl(p->fd, PHONE_REC_START)) {
|
||||
ast_log(LOG_WARNING, "Failed to start recording\n");
|
||||
return -1;
|
||||
}
|
||||
ioctl(p->fd, PHONE_REC_DEPTH, 3);
|
||||
ioctl(p->fd, PHONE_PLAY_DEPTH, 3);
|
||||
if (ioctl(p->fd, PHONE_PLAY_START)) {
|
||||
ast_log(LOG_WARNING, "Failed to start playback\n");
|
||||
return -1;
|
||||
}
|
||||
if (ioctl(p->fd, PHONE_REC_START)) {
|
||||
ast_log(LOG_WARNING, "Failed to start recording\n");
|
||||
return -1;
|
||||
}
|
||||
/* If we get here, we have a voice frame of Appropriate data */
|
||||
sofar = 0;
|
||||
@@ -562,14 +466,8 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame)
|
||||
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 0
|
||||
else
|
||||
ast_log(LOG_WARNING, "Only wrote %d of %d bytes\n", res, frame->datalen);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
sofar += res;
|
||||
@@ -585,9 +483,9 @@ static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *conte
|
||||
if (tmp) {
|
||||
snprintf(tmp->name, sizeof(tmp->name), "Phone/%s", i->dev + 5);
|
||||
tmp->type = type;
|
||||
tmp->fds[0] = i->fd;
|
||||
tmp->fd = i->fd;
|
||||
/* XXX Switching formats silently causes kernel panics XXX */
|
||||
tmp->nativeformats = prefformat;
|
||||
tmp->format = prefformat;
|
||||
tmp->state = state;
|
||||
if (state == AST_STATE_RING)
|
||||
tmp->rings = 1;
|
||||
@@ -598,23 +496,19 @@ static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *conte
|
||||
tmp->pvt->answer = phone_answer;
|
||||
tmp->pvt->read = phone_read;
|
||||
tmp->pvt->write = phone_write;
|
||||
tmp->pvt->exception = phone_exception;
|
||||
strncpy(tmp->context, context, sizeof(tmp->context));
|
||||
if (strlen(i->ext))
|
||||
strncpy(tmp->exten, i->ext, sizeof(tmp->exten));
|
||||
if (strlen(i->language))
|
||||
strncpy(tmp->language, i->language, sizeof(tmp->language));
|
||||
if (strlen(i->callerid))
|
||||
tmp->callerid = strdup(i->callerid);
|
||||
i->owner = tmp;
|
||||
ast_pthread_mutex_lock(&usecnt_lock);
|
||||
pthread_mutex_lock(&usecnt_lock);
|
||||
usecnt++;
|
||||
ast_pthread_mutex_unlock(&usecnt_lock);
|
||||
pthread_mutex_unlock(&usecnt_lock);
|
||||
ast_update_use_count();
|
||||
if (state != AST_STATE_DOWN) {
|
||||
if (state == AST_STATE_RING) {
|
||||
ioctl(tmp->fds[0], PHONE_RINGBACK);
|
||||
i->cpt = 1;
|
||||
ioctl(tmp->fd, PHONE_RINGBACK);
|
||||
}
|
||||
if (ast_pbx_start(tmp)) {
|
||||
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
|
||||
@@ -657,35 +551,34 @@ static void phone_check_exception(struct phone_pvt *i)
|
||||
i->dialtone = 0;
|
||||
if (strlen(i->ext) < AST_MAX_EXTENSION - 1)
|
||||
strcat(i->ext, digit);
|
||||
if (ast_exists_extension(NULL, i->context, i->ext, 1, i->callerid)) {
|
||||
if (ast_exists_extension(NULL, i->context, i->ext, 1)) {
|
||||
/* It's a valid extension in its context, get moving! */
|
||||
phone_new(i, AST_STATE_RING, i->context);
|
||||
/* No need to restart monitor, we are the monitor */
|
||||
if (i->owner) {
|
||||
ast_pthread_mutex_lock(&usecnt_lock);
|
||||
pthread_mutex_lock(&usecnt_lock);
|
||||
usecnt--;
|
||||
ast_pthread_mutex_unlock(&usecnt_lock);
|
||||
pthread_mutex_unlock(&usecnt_lock);
|
||||
ast_update_use_count();
|
||||
}
|
||||
} else if (!ast_canmatch_extension(NULL, i->context, i->ext, 1, i->callerid)) {
|
||||
} else if (!ast_canmatch_extension(NULL, i->context, i->ext, 1)) {
|
||||
/* There is nothing in the specified extension that can match anymore.
|
||||
Try the default */
|
||||
if (ast_exists_extension(NULL, "default", i->ext, 1, i->callerid)) {
|
||||
if (ast_exists_extension(NULL, "default", i->ext, 1)) {
|
||||
/* Check the default, too... */
|
||||
phone_new(i, AST_STATE_RING, "default");
|
||||
if (i->owner) {
|
||||
ast_pthread_mutex_lock(&usecnt_lock);
|
||||
pthread_mutex_lock(&usecnt_lock);
|
||||
usecnt--;
|
||||
ast_pthread_mutex_unlock(&usecnt_lock);
|
||||
pthread_mutex_unlock(&usecnt_lock);
|
||||
ast_update_use_count();
|
||||
}
|
||||
/* XXX This should probably be justified better XXX */
|
||||
} else if (!ast_canmatch_extension(NULL, "default", i->ext, 1, i->callerid)) {
|
||||
} else if (!ast_canmatch_extension(NULL, "default", i->ext, 1)) {
|
||||
/* It's not a valid extension, give a busy signal */
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "%s can't match anything in %s or default\n", i->ext, i->context);
|
||||
ioctl(i->fd, PHONE_BUSY);
|
||||
i->cpt = 1;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
@@ -699,9 +592,9 @@ static void phone_check_exception(struct phone_pvt *i)
|
||||
if (i->mode == MODE_IMMEDIATE) {
|
||||
phone_new(i, AST_STATE_RING, i->context);
|
||||
} else if (i->mode == MODE_DIALTONE) {
|
||||
ast_pthread_mutex_lock(&usecnt_lock);
|
||||
pthread_mutex_lock(&usecnt_lock);
|
||||
usecnt++;
|
||||
ast_pthread_mutex_unlock(&usecnt_lock);
|
||||
pthread_mutex_unlock(&usecnt_lock);
|
||||
ast_update_use_count();
|
||||
/* Reset the extension */
|
||||
i->ext[0] = '\0';
|
||||
@@ -710,31 +603,23 @@ static void phone_check_exception(struct phone_pvt *i)
|
||||
ioctl(i->fd, PHONE_PLAY_STOP);
|
||||
ioctl(i->fd, PHONE_PLAY_CODEC, ULAW);
|
||||
ioctl(i->fd, PHONE_PLAY_START);
|
||||
i->lastformat = -1;
|
||||
}
|
||||
} else {
|
||||
if (i->dialtone) {
|
||||
ast_pthread_mutex_lock(&usecnt_lock);
|
||||
pthread_mutex_lock(&usecnt_lock);
|
||||
usecnt--;
|
||||
ast_pthread_mutex_unlock(&usecnt_lock);
|
||||
pthread_mutex_unlock(&usecnt_lock);
|
||||
ast_update_use_count();
|
||||
}
|
||||
memset(i->ext, 0, sizeof(i->ext));
|
||||
if (i->cpt)
|
||||
{
|
||||
ioctl(i->fd, PHONE_CPT_STOP);
|
||||
i->cpt = 0;
|
||||
}
|
||||
ioctl(i->fd, PHONE_CPT_STOP);
|
||||
ioctl(i->fd, PHONE_PLAY_STOP);
|
||||
ioctl(i->fd, PHONE_REC_STOP);
|
||||
i->dialtone = 0;
|
||||
i->lastformat = -1;
|
||||
}
|
||||
}
|
||||
if (phonee.bits.pstn_ring) {
|
||||
if (phonee.bits.pstn_ring)
|
||||
ast_verbose("Unit is ringing\n");
|
||||
phone_new(i, AST_STATE_RING, i->context);
|
||||
}
|
||||
if (phonee.bits.caller_id)
|
||||
ast_verbose("We have caller ID\n");
|
||||
|
||||
@@ -760,14 +645,14 @@ static void *do_monitor(void *data)
|
||||
for(;;) {
|
||||
/* Don't let anybody kill us right away. Nobody should lock the interface list
|
||||
and wait for the monitor list, but the other way around is okay. */
|
||||
if (ast_pthread_mutex_lock(&monlock)) {
|
||||
if (pthread_mutex_lock(&monlock)) {
|
||||
ast_log(LOG_ERROR, "Unable to grab monitor lock\n");
|
||||
return NULL;
|
||||
}
|
||||
/* Lock the interface list */
|
||||
if (ast_pthread_mutex_lock(&iflock)) {
|
||||
if (pthread_mutex_lock(&iflock)) {
|
||||
ast_log(LOG_ERROR, "Unable to grab interface lock\n");
|
||||
ast_pthread_mutex_unlock(&monlock);
|
||||
pthread_mutex_unlock(&monlock);
|
||||
return NULL;
|
||||
}
|
||||
/* Build the stuff we're going to select on, that is the socket of every
|
||||
@@ -801,10 +686,10 @@ static void *do_monitor(void *data)
|
||||
i = i->next;
|
||||
}
|
||||
/* Okay, now that we know what to do, release the interface lock */
|
||||
ast_pthread_mutex_unlock(&iflock);
|
||||
pthread_mutex_unlock(&iflock);
|
||||
|
||||
/* And from now on, we're okay to be killed, so release the monitor lock as well */
|
||||
ast_pthread_mutex_unlock(&monlock);
|
||||
pthread_mutex_unlock(&monlock);
|
||||
/* Wait indefinitely for something to happen */
|
||||
if (dotone) {
|
||||
/* If we're ready to recycle the time, set it to 30 ms */
|
||||
@@ -833,7 +718,7 @@ static void *do_monitor(void *data)
|
||||
continue;
|
||||
/* Alright, lock the interface list again, and let's look and see what has
|
||||
happened */
|
||||
if (ast_pthread_mutex_lock(&iflock)) {
|
||||
if (pthread_mutex_lock(&iflock)) {
|
||||
ast_log(LOG_WARNING, "Unable to lock the interface list\n");
|
||||
continue;
|
||||
}
|
||||
@@ -855,7 +740,7 @@ static void *do_monitor(void *data)
|
||||
}
|
||||
i=i->next;
|
||||
}
|
||||
ast_pthread_mutex_unlock(&iflock);
|
||||
pthread_mutex_unlock(&iflock);
|
||||
}
|
||||
/* Never reached */
|
||||
return NULL;
|
||||
@@ -867,12 +752,12 @@ static int restart_monitor()
|
||||
/* If we're supposed to be stopped -- stay stopped */
|
||||
if (monitor_thread == -2)
|
||||
return 0;
|
||||
if (ast_pthread_mutex_lock(&monlock)) {
|
||||
if (pthread_mutex_lock(&monlock)) {
|
||||
ast_log(LOG_WARNING, "Unable to lock monitor\n");
|
||||
return -1;
|
||||
}
|
||||
if (monitor_thread == pthread_self()) {
|
||||
ast_pthread_mutex_unlock(&monlock);
|
||||
pthread_mutex_unlock(&monlock);
|
||||
ast_log(LOG_WARNING, "Cannot kill myself\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -884,19 +769,21 @@ static int restart_monitor()
|
||||
}
|
||||
/* Start a new monitor */
|
||||
if (pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) {
|
||||
ast_pthread_mutex_unlock(&monlock);
|
||||
pthread_mutex_unlock(&monlock);
|
||||
ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
|
||||
return -1;
|
||||
}
|
||||
ast_pthread_mutex_unlock(&monlock);
|
||||
pthread_mutex_unlock(&monlock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct phone_pvt *mkif(char *iface, int mode, int txgain, int rxgain)
|
||||
static struct phone_pvt *mkif(char *iface, int mode)
|
||||
{
|
||||
/* Make a phone_pvt structure for this interface */
|
||||
struct phone_pvt *tmp;
|
||||
#if 0
|
||||
int flags;
|
||||
#endif
|
||||
|
||||
tmp = malloc(sizeof(struct phone_pvt));
|
||||
if (tmp) {
|
||||
@@ -906,19 +793,10 @@ static struct phone_pvt *mkif(char *iface, int mode, int txgain, int rxgain)
|
||||
free(tmp);
|
||||
return NULL;
|
||||
}
|
||||
if (mode == MODE_FXO) {
|
||||
if (ioctl(tmp->fd, IXJCTL_PORT, PORT_PSTN))
|
||||
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");
|
||||
}
|
||||
ioctl(tmp->fd, PHONE_PLAY_STOP);
|
||||
ioctl(tmp->fd, PHONE_REC_STOP);
|
||||
ioctl(tmp->fd, PHONE_RING_STOP);
|
||||
ioctl(tmp->fd, PHONE_CPT_STOP);
|
||||
if (ioctl(tmp->fd, PHONE_PSTN_SET_STATE, PSTN_ON_HOOK))
|
||||
ast_log(LOG_DEBUG, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n",iface, strerror(errno));
|
||||
if (echocancel != AEC_OFF)
|
||||
ioctl(tmp->fd, IXJCTL_AEC_START, echocancel);
|
||||
if (silencesupression)
|
||||
@@ -927,8 +805,10 @@ static struct phone_pvt *mkif(char *iface, int mode, int txgain, int rxgain)
|
||||
ioctl(tmp->fd, PHONE_VAD, tmp->silencesupression);
|
||||
#endif
|
||||
tmp->mode = mode;
|
||||
#if 0
|
||||
flags = fcntl(tmp->fd, F_GETFL);
|
||||
fcntl(tmp->fd, F_SETFL, flags | O_NONBLOCK);
|
||||
#endif
|
||||
tmp->owner = NULL;
|
||||
tmp->lastformat = -1;
|
||||
tmp->lastinput = -1;
|
||||
@@ -940,12 +820,6 @@ static struct phone_pvt *mkif(char *iface, int mode, int txgain, int rxgain)
|
||||
tmp->next = NULL;
|
||||
tmp->obuflen = 0;
|
||||
tmp->dialtone = 0;
|
||||
tmp->cpt = 0;
|
||||
strncpy(tmp->callerid, callerid, sizeof(tmp->callerid));
|
||||
tmp->txgain = txgain;
|
||||
ioctl(tmp->fd, PHONE_PLAY_VOLUME, tmp->txgain);
|
||||
tmp->rxgain = rxgain;
|
||||
ioctl(tmp->fd, PHONE_REC_VOLUME, tmp->rxgain);
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
@@ -958,13 +832,13 @@ static struct ast_channel *phone_request(char *type, int format, void *data)
|
||||
char *name = data;
|
||||
|
||||
oldformat = format;
|
||||
format &= (AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW);
|
||||
format &= (AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR);
|
||||
if (!format) {
|
||||
ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", oldformat);
|
||||
return NULL;
|
||||
}
|
||||
/* Search for an unowned channel */
|
||||
if (ast_pthread_mutex_lock(&iflock)) {
|
||||
if (pthread_mutex_lock(&iflock)) {
|
||||
ast_log(LOG_ERROR, "Unable to lock interface list???\n");
|
||||
return NULL;
|
||||
}
|
||||
@@ -978,41 +852,17 @@ static struct ast_channel *phone_request(char *type, int format, void *data)
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
ast_pthread_mutex_unlock(&iflock);
|
||||
pthread_mutex_unlock(&iflock);
|
||||
restart_monitor();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/* parse gain value from config file */
|
||||
static int parse_gain_value(char *gain_type, char *value)
|
||||
{
|
||||
float gain;
|
||||
|
||||
/* try to scan number */
|
||||
if (sscanf(value, "%f", &gain) != 1)
|
||||
{
|
||||
ast_log(LOG_ERROR, "Invalid %s value '%s' in '%s' config\n",
|
||||
value, gain_type, config);
|
||||
return DEFAULT_GAIN;
|
||||
}
|
||||
|
||||
/* multiplicate gain by 1.0 gain value */
|
||||
gain = gain * (float)DEFAULT_GAIN;
|
||||
|
||||
/* percentage? */
|
||||
if (value[strlen(value) - 1] == '%')
|
||||
return (int)(gain / (float)100);
|
||||
|
||||
return (int)gain;
|
||||
}
|
||||
|
||||
int load_module()
|
||||
{
|
||||
struct ast_config *cfg;
|
||||
struct ast_variable *v;
|
||||
struct phone_pvt *tmp;
|
||||
int mode = MODE_IMMEDIATE;
|
||||
int txgain = DEFAULT_GAIN, rxgain = DEFAULT_GAIN; /* default gain 1.0 */
|
||||
cfg = ast_load(config);
|
||||
|
||||
/* We *must* have a config file otherwise stop immediately */
|
||||
@@ -1020,7 +870,7 @@ int load_module()
|
||||
ast_log(LOG_ERROR, "Unable to load config %s\n", config);
|
||||
return -1;
|
||||
}
|
||||
if (ast_pthread_mutex_lock(&iflock)) {
|
||||
if (pthread_mutex_lock(&iflock)) {
|
||||
/* It's a little silly to lock it, but we mind as well just to be sure */
|
||||
ast_log(LOG_ERROR, "Unable to lock interface list???\n");
|
||||
return -1;
|
||||
@@ -1029,7 +879,7 @@ int load_module()
|
||||
while(v) {
|
||||
/* Create the interface list */
|
||||
if (!strcasecmp(v->name, "device")) {
|
||||
tmp = mkif(v->value, mode, txgain, rxgain);
|
||||
tmp = mkif(v->value, mode);
|
||||
if (tmp) {
|
||||
tmp->next = iflist;
|
||||
iflist = tmp;
|
||||
@@ -1037,7 +887,7 @@ int load_module()
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Unable to register channel '%s'\n", v->value);
|
||||
ast_destroy(cfg);
|
||||
ast_pthread_mutex_unlock(&iflock);
|
||||
pthread_mutex_unlock(&iflock);
|
||||
unload_module();
|
||||
return -1;
|
||||
}
|
||||
@@ -1045,15 +895,11 @@ int load_module()
|
||||
silencesupression = ast_true(v->value);
|
||||
} else if (!strcasecmp(v->name, "language")) {
|
||||
strncpy(language, v->value, sizeof(language));
|
||||
} else if (!strcasecmp(v->name, "callerid")) {
|
||||
strncpy(callerid, v->value, sizeof(callerid));
|
||||
} else if (!strcasecmp(v->name, "mode")) {
|
||||
if (!strncasecmp(v->value, "di", 2))
|
||||
mode = MODE_DIALTONE;
|
||||
else if (!strncasecmp(v->value, "im", 2))
|
||||
mode = MODE_IMMEDIATE;
|
||||
else if (!strncasecmp(v->value, "fx", 2))
|
||||
mode = MODE_FXO;
|
||||
else
|
||||
ast_log(LOG_WARNING, "Unknown mode: %s\n", v->value);
|
||||
} else if (!strcasecmp(v->name, "context")) {
|
||||
@@ -1063,9 +909,7 @@ int load_module()
|
||||
prefformat = AST_FORMAT_G723_1;
|
||||
} else if (!strcasecmp(v->value, "slinear")) {
|
||||
prefformat = AST_FORMAT_SLINEAR;
|
||||
} else if (!strcasecmp(v->value, "ulaw")) {
|
||||
prefformat = AST_FORMAT_ULAW;
|
||||
} else
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Unknown format '%s'\n", v->value);
|
||||
} else if (!strcasecmp(v->name, "echocancel")) {
|
||||
if (!strcasecmp(v->value, "off")) {
|
||||
@@ -1078,17 +922,12 @@ int load_module()
|
||||
echocancel = AEC_HIGH;
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Unknown echo cancellation '%s'\n", v->value);
|
||||
} else if (!strcasecmp(v->name, "txgain")) {
|
||||
txgain = parse_gain_value(v->name, v->value);
|
||||
} else if (!strcasecmp(v->name, "rxgain")) {
|
||||
rxgain = parse_gain_value(v->name, v->value);
|
||||
}
|
||||
}
|
||||
v = v->next;
|
||||
}
|
||||
ast_pthread_mutex_unlock(&iflock);
|
||||
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)) {
|
||||
if (ast_channel_register(type, tdesc, AST_FORMAT_G723_1, phone_request)) {
|
||||
ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
|
||||
ast_destroy(cfg);
|
||||
unload_module();
|
||||
@@ -1107,7 +946,7 @@ int unload_module()
|
||||
struct phone_pvt *p, *pl;
|
||||
/* First, take us out of the channel loop */
|
||||
ast_channel_unregister(type);
|
||||
if (!ast_pthread_mutex_lock(&iflock)) {
|
||||
if (!pthread_mutex_lock(&iflock)) {
|
||||
/* Hangup all interfaces if they have an owner */
|
||||
p = iflist;
|
||||
while(p) {
|
||||
@@ -1116,24 +955,24 @@ int unload_module()
|
||||
p = p->next;
|
||||
}
|
||||
iflist = NULL;
|
||||
ast_pthread_mutex_unlock(&iflock);
|
||||
pthread_mutex_unlock(&iflock);
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Unable to lock the monitor\n");
|
||||
return -1;
|
||||
}
|
||||
if (!ast_pthread_mutex_lock(&monlock)) {
|
||||
if (!pthread_mutex_lock(&monlock)) {
|
||||
if (monitor_thread > -1) {
|
||||
pthread_cancel(monitor_thread);
|
||||
pthread_join(monitor_thread, NULL);
|
||||
}
|
||||
monitor_thread = -2;
|
||||
ast_pthread_mutex_unlock(&monlock);
|
||||
pthread_mutex_unlock(&monlock);
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Unable to lock the monitor\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!ast_pthread_mutex_lock(&iflock)) {
|
||||
if (!pthread_mutex_lock(&iflock)) {
|
||||
/* Destroy all the interfaces and free their memory */
|
||||
p = iflist;
|
||||
while(p) {
|
||||
@@ -1146,7 +985,7 @@ int unload_module()
|
||||
free(pl);
|
||||
}
|
||||
iflist = NULL;
|
||||
ast_pthread_mutex_unlock(&iflock);
|
||||
pthread_mutex_unlock(&iflock);
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Unable to lock the monitor\n");
|
||||
return -1;
|
||||
@@ -1158,9 +997,9 @@ int unload_module()
|
||||
int usecount()
|
||||
{
|
||||
int res;
|
||||
ast_pthread_mutex_lock(&usecnt_lock);
|
||||
pthread_mutex_lock(&usecnt_lock);
|
||||
res = usecnt;
|
||||
ast_pthread_mutex_unlock(&usecnt_lock);
|
||||
pthread_mutex_unlock(&usecnt_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1169,7 +1008,3 @@ char *description()
|
||||
return desc;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/if_packet.h>
|
||||
#include <linux/if_ether.h>
|
||||
@@ -253,8 +252,6 @@ static void vofr_dump_packet(struct vofr_hdr *vh, int len)
|
||||
|
||||
#endif
|
||||
|
||||
static struct ast_frame *vofr_read(struct ast_channel *ast);
|
||||
|
||||
static int vofr_xmit(struct vofr_pvt *p, char *data, int len)
|
||||
{
|
||||
int res;
|
||||
@@ -358,11 +355,11 @@ static int vofr_call(struct ast_channel *ast, char *dest, int timeout)
|
||||
while(otimeout) {
|
||||
otimeout = ast_waitfor(ast, 1000);
|
||||
if (otimeout < 1) {
|
||||
ast_log(LOG_WARNING, "Unable to take line '%s' off hook\n", ast->name);
|
||||
ast_log(LOG_WARNING, "Unable to take line off hook\n");
|
||||
/* Musta gotten hung up, or no ack on off hook */
|
||||
return -1;
|
||||
}
|
||||
f = vofr_read(ast);
|
||||
f = ast_read(ast);
|
||||
if (!f)
|
||||
return -1;
|
||||
if ((f->frametype == AST_FRAME_CONTROL) &&
|
||||
@@ -392,7 +389,7 @@ static int vofr_call(struct ast_channel *ast, char *dest, int timeout)
|
||||
/* Musta gotten hung up, or no ack on off hook */
|
||||
return -1;
|
||||
}
|
||||
f = vofr_read(ast);
|
||||
f = ast_read(ast);
|
||||
if (!f)
|
||||
return -1;
|
||||
|
||||
@@ -420,7 +417,7 @@ static int vofr_call(struct ast_channel *ast, char *dest, int timeout)
|
||||
timeout = res;
|
||||
if (res) {
|
||||
/* Ooh, read what's there. */
|
||||
f = vofr_read(ast);
|
||||
f = ast_read(ast);
|
||||
if (!f)
|
||||
return -1;
|
||||
if ((f->frametype == AST_FRAME_CONTROL) &&
|
||||
@@ -456,11 +453,11 @@ static int vofr_hangup(struct ast_channel *ast)
|
||||
ast->state = AST_STATE_DOWN;
|
||||
((struct vofr_pvt *)(ast->pvt->pvt))->owner = NULL;
|
||||
((struct vofr_pvt *)(ast->pvt->pvt))->ringgothangup = 0;
|
||||
ast_pthread_mutex_lock(&usecnt_lock);
|
||||
pthread_mutex_lock(&usecnt_lock);
|
||||
usecnt--;
|
||||
if (usecnt < 0)
|
||||
ast_log(LOG_WARNING, "Usecnt < 0???\n");
|
||||
ast_pthread_mutex_unlock(&usecnt_lock);
|
||||
pthread_mutex_unlock(&usecnt_lock);
|
||||
ast_update_use_count();
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
|
||||
@@ -486,7 +483,7 @@ static int vofr_answer(struct ast_channel *ast)
|
||||
while(cnt > 0) {
|
||||
cnt = ast_waitfor(ast, cnt);
|
||||
if (cnt > 0) {
|
||||
res = read(ast->fds[0], buf, sizeof(buf));
|
||||
res = read(ast->fd, buf, sizeof(buf));
|
||||
#ifdef VOFRDUMPER
|
||||
vofr_dump_packet((void *)(buf +FR_API_MESS), res - FR_API_MESS);
|
||||
#endif
|
||||
@@ -554,32 +551,18 @@ static struct ast_frame *vofr_read(struct ast_channel *ast)
|
||||
/* Read into the right place in the buffer, in case we send this
|
||||
as a voice frame. */
|
||||
CHECK_BLOCKING(ast);
|
||||
retry:
|
||||
res = read(p->s, ((char *)vh) - FR_API_MESS,
|
||||
G723_MAX_BUF - AST_FRIENDLY_OFFSET - sizeof(struct ast_frame) + sizeof(struct vofr_hdr) + FR_API_MESS);
|
||||
if (res < 0) {
|
||||
/* XXX HUGE BUG IN SANGOMA'S STACK: IT IGNORES O_NONBLOCK XXX */
|
||||
if (errno == EAGAIN) {
|
||||
fd_set fds;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(p->s, &fds);
|
||||
select(p->s + 1, &fds, NULL, NULL, NULL);
|
||||
goto retry;
|
||||
}
|
||||
ast->blocking = 0;
|
||||
ast_log(LOG_WARNING, "Read error on %s: %s (%d)\n", ast->name, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
ast->blocking = 0;
|
||||
|
||||
#ifdef VOFRDUMPER
|
||||
vofr_dump_packet((void *)(vh), res);
|
||||
#endif
|
||||
ast->blocking = 0;
|
||||
res -= FR_API_MESS;
|
||||
if (res < sizeof(struct vofr_hdr)) {
|
||||
if (res < sizeof(struct vofr_hdr *)) {
|
||||
ast_log(LOG_WARNING, "Nonsense frame on %s\n", ast->name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Some nice norms */
|
||||
fr->datalen = 0;
|
||||
fr->timelen = 0;
|
||||
@@ -701,7 +684,7 @@ retry:
|
||||
ast->state = AST_STATE_UP;
|
||||
return fr;
|
||||
} else if (ast->state != AST_STATE_UP) {
|
||||
ast_log(LOG_WARNING, "%s: Voice in weird state %d\n", ast->name, ast->state);
|
||||
ast_log(LOG_WARNING, "Voice in weird state %d\n", ast->state);
|
||||
}
|
||||
fr->frametype = AST_FRAME_VOICE;
|
||||
fr->subclass = AST_FORMAT_G723_1;
|
||||
@@ -784,17 +767,6 @@ static int vofr_write(struct ast_channel *ast, struct ast_frame *frame)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vofr_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
|
||||
{
|
||||
struct vofr_pvt *p = newchan->pvt->pvt;
|
||||
if (p->owner != oldchan) {
|
||||
ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, p->owner);
|
||||
return -1;
|
||||
}
|
||||
p->owner = newchan;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ast_channel *vofr_new(struct vofr_pvt *i, int state)
|
||||
{
|
||||
struct ast_channel *tmp;
|
||||
@@ -806,14 +778,12 @@ static struct ast_channel *vofr_new(struct vofr_pvt *i, int state)
|
||||
snprintf(tmp->name, sizeof(tmp->name), "AdtranVoFR/%s", i->sa.sll_device);
|
||||
#endif
|
||||
tmp->type = type;
|
||||
tmp->fds[0] = i->s;
|
||||
tmp->fd = i->s;
|
||||
/* Adtran VoFR supports only G723.1 format data. G711 (ulaw) would be nice too */
|
||||
tmp->nativeformats = AST_FORMAT_G723_1;
|
||||
tmp->format = AST_FORMAT_G723_1;
|
||||
tmp->state = state;
|
||||
if (state == AST_STATE_RING)
|
||||
tmp->rings = 1;
|
||||
tmp->writeformat = AST_FORMAT_G723_1;
|
||||
tmp->readformat = AST_FORMAT_G723_1;
|
||||
tmp->pvt->pvt = i;
|
||||
tmp->pvt->send_digit = vofr_digit;
|
||||
tmp->pvt->call = vofr_call;
|
||||
@@ -821,13 +791,12 @@ static struct ast_channel *vofr_new(struct vofr_pvt *i, int state)
|
||||
tmp->pvt->answer = vofr_answer;
|
||||
tmp->pvt->read = vofr_read;
|
||||
tmp->pvt->write = vofr_write;
|
||||
tmp->pvt->fixup = vofr_fixup;
|
||||
if (strlen(i->language))
|
||||
strncpy(tmp->language, i->language, sizeof(tmp->language));
|
||||
i->owner = tmp;
|
||||
ast_pthread_mutex_lock(&usecnt_lock);
|
||||
pthread_mutex_lock(&usecnt_lock);
|
||||
usecnt++;
|
||||
ast_pthread_mutex_unlock(&usecnt_lock);
|
||||
pthread_mutex_unlock(&usecnt_lock);
|
||||
ast_update_use_count();
|
||||
strncpy(tmp->context, i->context, sizeof(tmp->context));
|
||||
if (state != AST_STATE_DOWN) {
|
||||
@@ -915,14 +884,14 @@ static void *do_monitor(void *data)
|
||||
for(;;) {
|
||||
/* Don't let anybody kill us right away. Nobody should lock the interface list
|
||||
and wait for the monitor list, but the other way around is okay. */
|
||||
if (ast_pthread_mutex_lock(&monlock)) {
|
||||
if (pthread_mutex_lock(&monlock)) {
|
||||
ast_log(LOG_ERROR, "Unable to grab monitor lock\n");
|
||||
return NULL;
|
||||
}
|
||||
/* Lock the interface list */
|
||||
if (ast_pthread_mutex_lock(&iflock)) {
|
||||
if (pthread_mutex_lock(&iflock)) {
|
||||
ast_log(LOG_ERROR, "Unable to grab interface lock\n");
|
||||
ast_pthread_mutex_unlock(&monlock);
|
||||
pthread_mutex_unlock(&monlock);
|
||||
return NULL;
|
||||
}
|
||||
/* Build the stuff we're going to select on, that is the socket of every
|
||||
@@ -946,10 +915,10 @@ static void *do_monitor(void *data)
|
||||
i = i->next;
|
||||
}
|
||||
/* Okay, now that we know what to do, release the interface lock */
|
||||
ast_pthread_mutex_unlock(&iflock);
|
||||
pthread_mutex_unlock(&iflock);
|
||||
|
||||
/* And from now on, we're okay to be killed, so release the monitor lock as well */
|
||||
ast_pthread_mutex_unlock(&monlock);
|
||||
pthread_mutex_unlock(&monlock);
|
||||
pthread_testcancel();
|
||||
/* Wait indefinitely for something to happen */
|
||||
res = select(n + 1, &rfds, NULL, NULL, NULL);
|
||||
@@ -962,7 +931,7 @@ static void *do_monitor(void *data)
|
||||
}
|
||||
/* Alright, lock the interface list again, and let's look and see what has
|
||||
happened */
|
||||
if (ast_pthread_mutex_lock(&iflock)) {
|
||||
if (pthread_mutex_lock(&iflock)) {
|
||||
ast_log(LOG_WARNING, "Unable to lock the interface list\n");
|
||||
continue;
|
||||
}
|
||||
@@ -986,7 +955,7 @@ static void *do_monitor(void *data)
|
||||
}
|
||||
i=i->next;
|
||||
}
|
||||
ast_pthread_mutex_unlock(&iflock);
|
||||
pthread_mutex_unlock(&iflock);
|
||||
}
|
||||
/* Never reached */
|
||||
return NULL;
|
||||
@@ -998,27 +967,32 @@ static int restart_monitor(void)
|
||||
/* If we're supposed to be stopped -- stay stopped */
|
||||
if (monitor_thread == -2)
|
||||
return 0;
|
||||
if (ast_pthread_mutex_lock(&monlock)) {
|
||||
if (pthread_mutex_lock(&monlock)) {
|
||||
ast_log(LOG_WARNING, "Unable to lock monitor\n");
|
||||
return -1;
|
||||
}
|
||||
if (monitor_thread == pthread_self()) {
|
||||
ast_pthread_mutex_unlock(&monlock);
|
||||
pthread_mutex_unlock(&monlock);
|
||||
ast_log(LOG_WARNING, "Cannot kill myself\n");
|
||||
return -1;
|
||||
}
|
||||
if (monitor_thread) {
|
||||
/* Wake up the thread */
|
||||
#if 0
|
||||
pthread_cancel(monitor_thread);
|
||||
#endif
|
||||
pthread_kill(monitor_thread, SIGURG);
|
||||
} else {
|
||||
/* Start a new monitor */
|
||||
if (pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) {
|
||||
ast_pthread_mutex_unlock(&monlock);
|
||||
ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
|
||||
return -1;
|
||||
}
|
||||
#if 0
|
||||
pthread_join(monitor_thread, NULL);
|
||||
#endif
|
||||
}
|
||||
ast_pthread_mutex_unlock(&monlock);
|
||||
if (!monitor_thread)
|
||||
/* Start a new monitor */
|
||||
if (pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) {
|
||||
pthread_mutex_unlock(&monlock);
|
||||
ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
|
||||
return -1;
|
||||
}
|
||||
pthread_mutex_unlock(&monlock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1027,7 +1001,7 @@ static struct vofr_pvt *mkif(char *type, char *iface)
|
||||
/* Make a vofr_pvt structure for this interface */
|
||||
struct vofr_pvt *tmp;
|
||||
int sndbuf = 4096;
|
||||
|
||||
|
||||
tmp = malloc(sizeof(struct vofr_pvt));
|
||||
if (tmp) {
|
||||
|
||||
@@ -1118,19 +1092,19 @@ static struct ast_channel *vofr_request(char *type, int format, void *data)
|
||||
return NULL;
|
||||
}
|
||||
/* Search for an unowned channel */
|
||||
if (ast_pthread_mutex_lock(&iflock)) {
|
||||
if (pthread_mutex_lock(&iflock)) {
|
||||
ast_log(LOG_ERROR, "Unable to lock interface list???\n");
|
||||
return NULL;
|
||||
}
|
||||
p = iflist;
|
||||
while(p) {
|
||||
if (!p->owner && p->outgoing) {
|
||||
if (!p->owner) {
|
||||
tmp = vofr_new(p, AST_STATE_DOWN);
|
||||
break;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
ast_pthread_mutex_unlock(&iflock);
|
||||
pthread_mutex_unlock(&iflock);
|
||||
restart_monitor();
|
||||
return tmp;
|
||||
}
|
||||
@@ -1147,7 +1121,7 @@ int load_module()
|
||||
ast_log(LOG_ERROR, "Unable to load config %s\n", config);
|
||||
return -1;
|
||||
}
|
||||
if (ast_pthread_mutex_lock(&iflock)) {
|
||||
if (pthread_mutex_lock(&iflock)) {
|
||||
/* It's a little silly to lock it, but we mind as well just to be sure */
|
||||
ast_log(LOG_ERROR, "Unable to lock interface list???\n");
|
||||
return -1;
|
||||
@@ -1164,7 +1138,7 @@ int load_module()
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Unable to register channel '%s'\n", v->value);
|
||||
ast_destroy(cfg);
|
||||
ast_pthread_mutex_unlock(&iflock);
|
||||
pthread_mutex_unlock(&iflock);
|
||||
unload_module();
|
||||
return -1;
|
||||
}
|
||||
@@ -1175,7 +1149,7 @@ int load_module()
|
||||
}
|
||||
v = v->next;
|
||||
}
|
||||
ast_pthread_mutex_unlock(&iflock);
|
||||
pthread_mutex_unlock(&iflock);
|
||||
/* Make sure we can register our AdtranVoFR channel type */
|
||||
if (ast_channel_register(type, tdesc, AST_FORMAT_G723_1, vofr_request)) {
|
||||
ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
|
||||
@@ -1194,7 +1168,7 @@ int unload_module()
|
||||
struct vofr_pvt *p, *pl;
|
||||
/* First, take us out of the channel loop */
|
||||
ast_channel_unregister(type);
|
||||
if (!ast_pthread_mutex_lock(&iflock)) {
|
||||
if (!pthread_mutex_lock(&iflock)) {
|
||||
/* Hangup all interfaces if they have an owner */
|
||||
p = iflist;
|
||||
while(p) {
|
||||
@@ -1203,25 +1177,25 @@ int unload_module()
|
||||
p = p->next;
|
||||
}
|
||||
iflist = NULL;
|
||||
ast_pthread_mutex_unlock(&iflock);
|
||||
pthread_mutex_unlock(&iflock);
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Unable to lock the monitor\n");
|
||||
return -1;
|
||||
}
|
||||
if (!ast_pthread_mutex_lock(&monlock)) {
|
||||
if (!pthread_mutex_lock(&monlock)) {
|
||||
if (monitor_thread) {
|
||||
pthread_cancel(monitor_thread);
|
||||
pthread_kill(monitor_thread, SIGURG);
|
||||
pthread_join(monitor_thread, NULL);
|
||||
}
|
||||
monitor_thread = -2;
|
||||
ast_pthread_mutex_unlock(&monlock);
|
||||
pthread_mutex_unlock(&monlock);
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Unable to lock the monitor\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!ast_pthread_mutex_lock(&iflock)) {
|
||||
if (!pthread_mutex_lock(&iflock)) {
|
||||
/* Destroy all the interfaces and free their memory */
|
||||
p = iflist;
|
||||
while(p) {
|
||||
@@ -1234,7 +1208,7 @@ int unload_module()
|
||||
free(pl);
|
||||
}
|
||||
iflist = NULL;
|
||||
ast_pthread_mutex_unlock(&iflock);
|
||||
pthread_mutex_unlock(&iflock);
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Unable to lock the monitor\n");
|
||||
return -1;
|
||||
@@ -1246,17 +1220,12 @@ int unload_module()
|
||||
int usecount()
|
||||
{
|
||||
int res;
|
||||
ast_pthread_mutex_lock(&usecnt_lock);
|
||||
pthread_mutex_lock(&usecnt_lock);
|
||||
res = usecnt;
|
||||
ast_pthread_mutex_unlock(&usecnt_lock);
|
||||
pthread_mutex_unlock(&usecnt_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
char *description()
|
||||
{
|
||||
return desc;
|
||||
|
||||
4288
channels/chan_zap.c
4288
channels/chan_zap.c
File diff suppressed because it is too large
Load Diff
@@ -1,95 +0,0 @@
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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 gensound. %d samples */\n", fn, freq1, freq2, samples);
|
||||
else
|
||||
fprintf(f, "/* %s: Generated from frequency %d\n"
|
||||
" by gensound. %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);
|
||||
if (freq2)
|
||||
val += loudness * sin((freq2 * 2.0 * M_PI * x)/8000.0);
|
||||
fprintf(f, "%5d, ", (int)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;
|
||||
}
|
||||
@@ -38,25 +38,6 @@
|
||||
#define AST_IAX_COMMAND_INVAL 10
|
||||
#define AST_IAX_COMMAND_LAGRQ 11
|
||||
#define AST_IAX_COMMAND_LAGRP 12
|
||||
#define AST_IAX_COMMAND_REGREQ 13 /* Registration request */
|
||||
#define AST_IAX_COMMAND_REGAUTH 14 /* Registration authentication required */
|
||||
#define AST_IAX_COMMAND_REGACK 15 /* Registration accepted */
|
||||
#define AST_IAX_COMMAND_REGREJ 16 /* Registration rejected */
|
||||
#define AST_IAX_COMMAND_REGREL 17 /* Force release of registration */
|
||||
#define AST_IAX_COMMAND_VNAK 18 /* If we receive voice before valid first voice frame, send this */
|
||||
#define AST_IAX_COMMAND_DPREQ 19 /* Request status of a dialplan entry */
|
||||
#define AST_IAX_COMMAND_DPREP 20 /* Request status of a dialplan entry */
|
||||
#define AST_IAX_COMMAND_DIAL 21 /* Request a dial on channel brought up TBD */
|
||||
#define AST_IAX_COMMAND_TXREQ 22 /* Transfer Request */
|
||||
#define AST_IAX_COMMAND_TXCNT 23 /* Transfer Connect */
|
||||
#define AST_IAX_COMMAND_TXACC 24 /* Transfer Accepted */
|
||||
#define AST_IAX_COMMAND_TXREADY 25 /* Transfer ready */
|
||||
#define AST_IAX_COMMAND_TXREL 26 /* Transfer release */
|
||||
#define AST_IAX_COMMAND_TXREJ 27 /* Transfer reject */
|
||||
#define AST_IAX_COMMAND_QUELCH 28 /* Stop audio/video transmission */
|
||||
#define AST_IAX_COMMAND_UNQUELCH 29 /* Resume audio/video transmission */
|
||||
|
||||
#define AST_DEFAULT_REG_EXPIRE 60 /* By default require re-registration once per minute */
|
||||
|
||||
#define AST_DEFAULT_IAX_PORTNO 5036
|
||||
|
||||
@@ -74,7 +55,7 @@ struct ast_iax_full_hdr {
|
||||
/* Mini header is used only for voice frames -- delivered unreliably */
|
||||
struct ast_iax_mini_hdr {
|
||||
short callno; /* Source call number -- high bit must be 0 */
|
||||
unsigned short ts; /* 16-bit Timestamp (high 16 bits from last ast_iax_full_hdr) */
|
||||
unsigned short ts; /* 16-bit Timestamp (high 32 bits from last ast_iax_full_hdr) */
|
||||
/* Frametype implicitly VOICE_FRAME */
|
||||
/* subclass implicit from last ast_iax_full_hdr */
|
||||
char data[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.4 1999/12/01 05:25:58 markster
|
||||
Version 0.1.3 from FTP
|
||||
|
||||
Revision 1.1 1999/12/01 05:25:58 markster
|
||||
Start on the Internet Phone Jack channel
|
||||
|
||||
1752
channels/ring10.h
1752
channels/ring10.h
File diff suppressed because it is too large
Load Diff
193
cli.c
193
cli.c
@@ -27,11 +27,6 @@
|
||||
#include <readline/readline.h>
|
||||
/* For module directory */
|
||||
#include "asterisk.h"
|
||||
#include "build.h"
|
||||
|
||||
#define VERSION_INFO "Asterisk " ASTERISK_VERSION " built by " BUILD_USER "@" BUILD_HOSTNAME \
|
||||
" on a " BUILD_MACHINE " running " BUILD_OS
|
||||
|
||||
|
||||
void ast_cli(int fd, char *fmt, ...)
|
||||
{
|
||||
@@ -71,21 +66,6 @@ static char chanlist_help[] =
|
||||
" Lists currently defined channels and some information about\n"
|
||||
" them.\n";
|
||||
|
||||
static char reload_help[] =
|
||||
"Usage: reload\n"
|
||||
" Reloads configuration files for all modules which support\n"
|
||||
" reloading.\n";
|
||||
|
||||
static char set_verbose_help[] =
|
||||
"Usage: set verbose <level>\n"
|
||||
" Sets level of verbose messages to be displayed. 0 means\n"
|
||||
" no messages should be displayed.\n";
|
||||
|
||||
static char softhangup_help[] =
|
||||
"Usage: soft hangup <channel>\n"
|
||||
" Request that a channel be hung up. The hangup takes effect\n"
|
||||
" the next time the driver reads or writes from the channel\n";
|
||||
|
||||
static int handle_load(int fd, int argc, char *argv[])
|
||||
{
|
||||
if (argc != 2)
|
||||
@@ -97,32 +77,6 @@ static int handle_load(int fd, int argc, char *argv[])
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static int handle_reload(int fd, int argc, char *argv[])
|
||||
{
|
||||
if (argc != 1)
|
||||
return RESULT_SHOWUSAGE;
|
||||
ast_module_reload();
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static int handle_set_verbose(int fd, int argc, char *argv[])
|
||||
{
|
||||
int val;
|
||||
/* Has a hidden 'at least' argument */
|
||||
if ((argc != 3) && (argc != 4))
|
||||
return RESULT_SHOWUSAGE;
|
||||
if ((argc == 4) && strcasecmp(argv[2], "atleast"))
|
||||
return RESULT_SHOWUSAGE;
|
||||
if (argc == 3)
|
||||
option_verbose = atoi(argv[2]);
|
||||
else {
|
||||
val = atoi(argv[3]);
|
||||
if (val > option_verbose)
|
||||
option_verbose = val;
|
||||
}
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static int handle_unload(int fd, int argc, char *argv[])
|
||||
{
|
||||
int x;
|
||||
@@ -168,41 +122,30 @@ static char modlist_help[] =
|
||||
" Shows Asterisk modules currently in use, and usage "
|
||||
"statistics.\n";
|
||||
|
||||
static char version_help[] =
|
||||
"Usage: show version\n"
|
||||
" Shows Asterisk version information.\n ";
|
||||
|
||||
static int handle_modlist(int fd, int argc, char *argv[])
|
||||
{
|
||||
if (argc != 2)
|
||||
return RESULT_SHOWUSAGE;
|
||||
ast_pthread_mutex_lock(&climodentrylock);
|
||||
pthread_mutex_lock(&climodentrylock);
|
||||
climodentryfd = fd;
|
||||
ast_cli(fd, MODLIST_FORMAT2, "Module", "Description", "Use Count");
|
||||
ast_update_module_list(modlist_modentry);
|
||||
climodentryfd = -1;
|
||||
ast_pthread_mutex_unlock(&climodentrylock);
|
||||
pthread_mutex_unlock(&climodentrylock);
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static int handle_version(int fd, int argc, char *argv[])
|
||||
{
|
||||
if (argc != 2)
|
||||
return RESULT_SHOWUSAGE;
|
||||
ast_cli(fd, "%s\n", VERSION_INFO);
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
static int handle_chanlist(int fd, int argc, char *argv[])
|
||||
{
|
||||
#define FORMAT_STRING "%15s (%-10s %-12s %-4d) %7s %-12s %-15s\n"
|
||||
#define FORMAT_STRING2 "%15s (%-10s %-12s %-4s) %7s %-12s %-15s\n"
|
||||
#define FORMAT_STRING "%15s (%-10s %-12s %-4d) %-12s %-15s\n"
|
||||
#define FORMAT_STRING2 "%15s (%-10s %-12s %-4s) %-12s %-15s\n"
|
||||
struct ast_channel *c=NULL;
|
||||
if (argc != 2)
|
||||
return RESULT_SHOWUSAGE;
|
||||
c = ast_channel_walk(NULL);
|
||||
ast_cli(fd, FORMAT_STRING2, "Channel", "Context", "Extension", "Pri", "State", "Appl.", "Data");
|
||||
ast_cli(fd, FORMAT_STRING2, "Channel", "Context", "Extension", "Pri", "Appl.", "Data");
|
||||
while(c) {
|
||||
ast_cli(fd, FORMAT_STRING, c->name, c->context, c->exten, c->priority, ast_state2str(c->state),
|
||||
ast_cli(fd, FORMAT_STRING, c->name, c->context, c->exten, c->priority,
|
||||
c->appl ? c->appl : "(None)", c->data ? ( strlen(c->data) ? c->data : "(Empty)" ): "(None)");
|
||||
c = ast_channel_walk(c);
|
||||
}
|
||||
@@ -213,52 +156,6 @@ static char showchan_help[] =
|
||||
"Usage: show channel <channel>\n"
|
||||
" Shows lots of information about the specified channel.\n";
|
||||
|
||||
static char commandcomplete_help[] =
|
||||
"Usage: _command complete \"<line>\" text state\n"
|
||||
" This function is used internally to help with command completion and should.\n"
|
||||
" never be called by the user directly.\n";
|
||||
|
||||
static int handle_softhangup(int fd, int argc, char *argv[])
|
||||
{
|
||||
struct ast_channel *c=NULL;
|
||||
if (argc != 3)
|
||||
return RESULT_SHOWUSAGE;
|
||||
c = ast_channel_walk(NULL);
|
||||
while(c) {
|
||||
if (!strcasecmp(c->name, argv[2])) {
|
||||
ast_cli(fd, "Requested Hangup on channel '%s'\n", c->name);
|
||||
c->softhangup = 1;
|
||||
break;
|
||||
}
|
||||
c = ast_channel_walk(c);
|
||||
}
|
||||
if (!c)
|
||||
ast_cli(fd, "%s is not a known channel\n", argv[2]);
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static char *__ast_cli_generator(char *text, char *word, int state, int lock);
|
||||
|
||||
static int handle_commandcomplete(int fd, int argc, char *argv[])
|
||||
{
|
||||
char *buf;
|
||||
#if 0
|
||||
printf("Search for %d args: '%s', '%s', '%s', '%s'\n", argc, argv[0], argv[1], argv[2], argv[3]);
|
||||
#endif
|
||||
if (argc != 5)
|
||||
return RESULT_SHOWUSAGE;
|
||||
buf = __ast_cli_generator(argv[2], argv[3], atoi(argv[4]), 0);
|
||||
#if 0
|
||||
printf("Search for '%s' %s %d got '%s'\n", argv[2], argv[3], atoi(argv[4]), buf);
|
||||
#endif
|
||||
if (buf) {
|
||||
ast_cli(fd, buf);
|
||||
free(buf);
|
||||
} else
|
||||
ast_cli(fd, "NULL\n");
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static int handle_showchan(int fd, int argc, char *argv[])
|
||||
{
|
||||
struct ast_channel *c=NULL;
|
||||
@@ -271,14 +168,14 @@ static int handle_showchan(int fd, int argc, char *argv[])
|
||||
" -- General --\n"
|
||||
" Name: %s\n"
|
||||
" Type: %s\n"
|
||||
" Translator: %s\n"
|
||||
" Master: %s\n"
|
||||
" Caller ID: %s\n"
|
||||
" DNID Digits: %s\n"
|
||||
" State: %s (%d)\n"
|
||||
" State: %d\n"
|
||||
" Rings: %d\n"
|
||||
" WriteFormat: %d\n"
|
||||
" ReadFormat: %d\n"
|
||||
" NativeFormat: %d\n"
|
||||
"1st File Descriptor: %d\n"
|
||||
" Format: %d\n"
|
||||
"File Descriptor: %d\n"
|
||||
" -- PBX --\n"
|
||||
" Context: %s\n"
|
||||
" Extension: %s\n"
|
||||
@@ -287,10 +184,10 @@ static int handle_showchan(int fd, int argc, char *argv[])
|
||||
" Data: %s\n"
|
||||
" Stack: %d\n"
|
||||
" Blocking in: %s\n",
|
||||
c->name, c->type,
|
||||
(c->callerid ? c->callerid : "(N/A)"),
|
||||
(c->dnid ? c->dnid : "(N/A)" ), ast_state2str(c->state), c->state, c->rings, c->nativeformats, c->writeformat, c->readformat,
|
||||
c->fds[0], c->context, c->exten, c->priority, ( c->appl ? c->appl : "(N/A)" ),
|
||||
c->name, c->type, (c->trans ? c->trans->name : "(N/A)"),
|
||||
(c->master ? c->master->name : "(N/A)"), (c->callerid ? c->callerid : "(N/A)"),
|
||||
(c->dnid ? c->dnid : "(N/A)" ), c->state, c->rings, c->format,
|
||||
c->fd, c->context, c->exten, c->priority, ( c->appl ? c->appl : "(N/A)" ),
|
||||
( c-> data ? (strlen(c->data) ? c->data : "(Empty)") : "(None)"),
|
||||
c->stack, (c->blocking ? c->blockproc : "(Not Blocking)"));
|
||||
|
||||
@@ -309,10 +206,8 @@ static char *complete_ch(char *line, char *word, int pos, int state)
|
||||
int which=0;
|
||||
c = ast_channel_walk(NULL);
|
||||
while(c) {
|
||||
if (!strncasecmp(word, c->name, strlen(word))) {
|
||||
if (++which > state)
|
||||
break;
|
||||
}
|
||||
if (++which > state)
|
||||
break;
|
||||
c = ast_channel_walk(c);
|
||||
}
|
||||
return c ? strdup(c->name) : NULL;
|
||||
@@ -328,7 +223,7 @@ static char *complete_fn(char *line, char *word, int pos, int state)
|
||||
strncpy(filename, word, sizeof(filename));
|
||||
else
|
||||
snprintf(filename, sizeof(filename), "%s/%s", AST_MODULE_DIR, word);
|
||||
c = (char*)filename_completion_function(filename, state);
|
||||
c = filename_completion_function(filename, state);
|
||||
if (c && word[0] != '/')
|
||||
c += (strlen(AST_MODULE_DIR) + 1);
|
||||
return c ? strdup(c) : c;
|
||||
@@ -339,15 +234,10 @@ static int handle_help(int fd, int argc, char *argv[]);
|
||||
static struct ast_cli_entry builtins[] = {
|
||||
/* Keep alphabetized */
|
||||
{ { "help", NULL }, handle_help, "Display help list, or specific help on a command", help_help },
|
||||
{ { "_command", "complete", NULL }, handle_commandcomplete, "Command complete", commandcomplete_help },
|
||||
{ { "load", NULL }, handle_load, "Load a dynamic module by name", load_help, complete_fn },
|
||||
{ { "reload", NULL }, handle_reload, "Reload configuration", reload_help },
|
||||
{ { "set", "verbose", NULL }, handle_set_verbose, "Set level of verboseness", set_verbose_help },
|
||||
{ { "show", "channel", NULL }, handle_showchan, "Display information on a specific channel", showchan_help, complete_ch },
|
||||
{ { "show", "channels", NULL }, handle_chanlist, "Display information on channels", chanlist_help },
|
||||
{ { "show", "modules", NULL }, handle_modlist, "List modules and info", modlist_help },
|
||||
{ { "show", "version", NULL }, handle_version, "Display version info", version_help },
|
||||
{ { "soft", "hangup", NULL }, handle_softhangup, "Request a hangup on a given channel", softhangup_help, complete_ch },
|
||||
{ { "show", "modules", NULL }, handle_modlist, "List modules and info", modlist_help },
|
||||
{ { "unload", NULL }, handle_unload, "Unload a dynamic module by name", unload_help, complete_fn },
|
||||
{ { NULL }, NULL, NULL, NULL }
|
||||
};
|
||||
@@ -437,7 +327,7 @@ static char *find_best(char *argv[])
|
||||
int ast_cli_unregister(struct ast_cli_entry *e)
|
||||
{
|
||||
struct ast_cli_entry *cur, *l=NULL;
|
||||
ast_pthread_mutex_lock(&clilock);
|
||||
pthread_mutex_lock(&clilock);
|
||||
cur = helpers;
|
||||
while(cur) {
|
||||
if (e == cur) {
|
||||
@@ -452,7 +342,7 @@ int ast_cli_unregister(struct ast_cli_entry *e)
|
||||
l = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
ast_pthread_mutex_unlock(&clilock);
|
||||
pthread_mutex_unlock(&clilock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -461,11 +351,11 @@ int ast_cli_register(struct ast_cli_entry *e)
|
||||
struct ast_cli_entry *cur, *l=NULL;
|
||||
char fulle[80], fulltst[80];
|
||||
static int len;
|
||||
ast_pthread_mutex_lock(&clilock);
|
||||
pthread_mutex_lock(&clilock);
|
||||
join2(fulle, sizeof(fulle), e->cmda);
|
||||
if (find_cli(e->cmda, -1)) {
|
||||
ast_pthread_mutex_unlock(&clilock);
|
||||
ast_log(LOG_WARNING, "Command '%s' already registered (or something close enough)\n", fulle);
|
||||
pthread_mutex_unlock(&clilock);
|
||||
return -1;
|
||||
}
|
||||
cur = helpers;
|
||||
@@ -494,7 +384,7 @@ int ast_cli_register(struct ast_cli_entry *e)
|
||||
helpers = e;
|
||||
e->next = NULL;
|
||||
}
|
||||
ast_pthread_mutex_unlock(&clilock);
|
||||
pthread_mutex_unlock(&clilock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -527,9 +417,6 @@ static int help_workhorse(int fd, char *match[])
|
||||
fullcmd = fullcmd1;
|
||||
e1++;
|
||||
}
|
||||
/* Hide commands that start with '_' */
|
||||
if (fullcmd[0] == '_')
|
||||
continue;
|
||||
if (match) {
|
||||
if (strncasecmp(matchstr, fullcmd, strlen(matchstr))) {
|
||||
continue;
|
||||
@@ -582,11 +469,6 @@ static char *parse_args(char *s, int *max, char *argv[])
|
||||
goto normal;
|
||||
else
|
||||
quoted = !quoted;
|
||||
if (quoted && whitespace) {
|
||||
/* If we're starting a quote, coming off white space start a new word, too */
|
||||
argv[x++] = cur;
|
||||
whitespace=0;
|
||||
}
|
||||
escaped = 0;
|
||||
break;
|
||||
case ' ':
|
||||
@@ -632,7 +514,7 @@ normal:
|
||||
return dup;
|
||||
}
|
||||
|
||||
static char *__ast_cli_generator(char *text, char *word, int state, int lock)
|
||||
char *ast_cli_generator(char *text, char *word, int state)
|
||||
{
|
||||
char *argv[AST_MAX_ARGS];
|
||||
struct ast_cli_entry *e, *e1, *e2;
|
||||
@@ -646,8 +528,7 @@ static char *__ast_cli_generator(char *text, char *word, int state, int lock)
|
||||
|
||||
if ((dup = parse_args(text, &x, argv))) {
|
||||
join(matchstr, sizeof(matchstr), argv);
|
||||
if (lock)
|
||||
ast_pthread_mutex_lock(&clilock);
|
||||
pthread_mutex_lock(&clilock);
|
||||
e1 = builtins;
|
||||
e2 = helpers;
|
||||
while(e1->cmda[0] || e2) {
|
||||
@@ -655,7 +536,7 @@ static char *__ast_cli_generator(char *text, char *word, int state, int lock)
|
||||
join(fullcmd2, sizeof(fullcmd2), e2->cmda);
|
||||
if (e1->cmda[0])
|
||||
join(fullcmd1, sizeof(fullcmd1), e1->cmda);
|
||||
if (!e1->cmda[0] ||
|
||||
if (!e1->cmda ||
|
||||
(e2 && (strcmp(fullcmd2, fullcmd1) < 0))) {
|
||||
/* Use e2 */
|
||||
e = e2;
|
||||
@@ -668,7 +549,7 @@ static char *__ast_cli_generator(char *text, char *word, int state, int lock)
|
||||
fullcmd = fullcmd1;
|
||||
e1++;
|
||||
}
|
||||
if ((fullcmd[0] != '_') && !strncasecmp(matchstr, fullcmd, strlen(matchstr))) {
|
||||
if (!strncasecmp(matchstr, fullcmd, strlen(matchstr))) {
|
||||
/* We contain the first part of one or more commands */
|
||||
matchnum++;
|
||||
if (matchnum > state) {
|
||||
@@ -679,8 +560,7 @@ static char *__ast_cli_generator(char *text, char *word, int state, int lock)
|
||||
res = e->cmda[x];
|
||||
}
|
||||
if (res) {
|
||||
if (lock)
|
||||
ast_pthread_mutex_unlock(&clilock);
|
||||
pthread_mutex_unlock(&clilock);
|
||||
return res ? strdup(res) : NULL;
|
||||
}
|
||||
}
|
||||
@@ -689,24 +569,17 @@ static char *__ast_cli_generator(char *text, char *word, int state, int lock)
|
||||
/* We have a command in its entirity within us -- theoretically only one
|
||||
command can have this occur */
|
||||
fullcmd = e->generator(text, word, (strlen(word) ? (x - 1) : (x)), state);
|
||||
if (lock)
|
||||
ast_pthread_mutex_unlock(&clilock);
|
||||
pthread_mutex_unlock(&clilock);
|
||||
return fullcmd;
|
||||
}
|
||||
|
||||
}
|
||||
if (lock)
|
||||
ast_pthread_mutex_unlock(&clilock);
|
||||
pthread_mutex_unlock(&clilock);
|
||||
free(dup);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *ast_cli_generator(char *text, char *word, int state)
|
||||
{
|
||||
return __ast_cli_generator(text, word, state, 1);
|
||||
}
|
||||
|
||||
int ast_cli_command(int fd, char *s)
|
||||
{
|
||||
char *argv[AST_MAX_ARGS];
|
||||
@@ -717,7 +590,7 @@ int ast_cli_command(int fd, char *s)
|
||||
if ((dup = parse_args(s, &x, argv))) {
|
||||
/* We need at least one entry, or ignore */
|
||||
if (x > 0) {
|
||||
ast_pthread_mutex_lock(&clilock);
|
||||
pthread_mutex_lock(&clilock);
|
||||
e = find_cli(argv, 0);
|
||||
if (e) {
|
||||
switch(e->handler(fd, x, argv)) {
|
||||
@@ -728,7 +601,7 @@ 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);
|
||||
pthread_mutex_unlock(&clilock);
|
||||
}
|
||||
free(dup);
|
||||
} else {
|
||||
|
||||
@@ -28,7 +28,7 @@ LIBGSM=gsm/lib/libgsm.a
|
||||
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
|
||||
|
||||
all: $(CODECS)
|
||||
|
||||
@@ -71,7 +71,7 @@ codec_lpc10.so: codec_lpc10.o $(LIBLPC10)
|
||||
$(CC) -shared -Xlinker -x -o $@ $< $(LIBLPC10) -lm
|
||||
|
||||
codec_mp3_d.so: codec_mp3_d.o $(LIBMP3)
|
||||
$(CC) -lm -shared -Xlinker -x -o $@ $< $(LIBMP3)
|
||||
$(CC) -shared -Xlinker -x -o $@ $< $(LIBMP3)
|
||||
|
||||
%.so : %.o
|
||||
$(CC) -shared -Xlinker -x -o $@ $<
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* adpcm_slin_ex.h --
|
||||
*
|
||||
* 4-bit ADPCM data, 20 milliseconds worth at 8 kHz.
|
||||
*
|
||||
* Source: g723.example
|
||||
*
|
||||
* Copyright (C) 2001, Linux Support Services, Inc.
|
||||
*
|
||||
* Distributed under the terms of the GNU General Public License
|
||||
*
|
||||
*/
|
||||
|
||||
static unsigned char adpcm_slin_ex[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
@@ -1,546 +0,0 @@
|
||||
/* codec_adpcm.c - translate between signed linear and Dialogic ADPCM
|
||||
*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Based on frompcm.c and topcm.c from the Emiliano MIPL browser/
|
||||
* interpreter. See http://www.bsdtelephony.com.mx
|
||||
*
|
||||
* Copyright (c) 2001 Linux Support Services, Inc. All rights reserved.
|
||||
*
|
||||
* Karl Sackett <krs@linux-support.net>, 2001-3-21
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/channel.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 = PTHREAD_MUTEX_INITIALIZER;
|
||||
static int localusecnt = 0;
|
||||
|
||||
static char *tdesc = "Adaptive Differential PCM Coder/Decoder";
|
||||
|
||||
/* Sample frame data */
|
||||
|
||||
#include "slin_adpcm_ex.h"
|
||||
#include "adpcm_slin_ex.h"
|
||||
|
||||
/*
|
||||
* Step size index shift table
|
||||
*/
|
||||
|
||||
static short indsft[8] = { -1, -1, -1, -1, 2, 4, 6, 8 };
|
||||
|
||||
/*
|
||||
* Step size table, where stpsz[i]=floor[16*(11/10)^i]
|
||||
*/
|
||||
|
||||
static short stpsz[49] = {
|
||||
16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 60, 66, 73,
|
||||
80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230, 253, 279,
|
||||
307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963,
|
||||
1060, 1166, 1282, 1411, 1552
|
||||
};
|
||||
|
||||
/*
|
||||
* Nibble to bit map
|
||||
*/
|
||||
|
||||
static short nbl2bit[16][4] = {
|
||||
{1, 0, 0, 0}, {1, 0, 0, 1}, {1, 0, 1, 0}, {1, 0, 1, 1},
|
||||
{1, 1, 0, 0}, {1, 1, 0, 1}, {1, 1, 1, 0}, {1, 1, 1, 1},
|
||||
{-1, 0, 0, 0}, {-1, 0, 0, 1}, {-1, 0, 1, 0}, {-1, 0, 1, 1},
|
||||
{-1, 1, 0, 0}, {-1, 1, 0, 1}, {-1, 1, 1, 0}, {-1, 1, 1, 1}
|
||||
};
|
||||
|
||||
/*
|
||||
* Decode(encoded)
|
||||
* Decodes the encoded nibble from the adpcm file.
|
||||
*
|
||||
* Results:
|
||||
* Returns the encoded difference.
|
||||
*
|
||||
* Side effects:
|
||||
* Sets the index to the step size table for the next encode.
|
||||
*/
|
||||
|
||||
static inline short
|
||||
decode (unsigned char encoded, short *ssindex)
|
||||
{
|
||||
short diff, step;
|
||||
step = stpsz[*ssindex];
|
||||
diff = nbl2bit[encoded][0] * (step * nbl2bit[encoded][1] +
|
||||
(step >> 1) * nbl2bit[encoded][2] +
|
||||
(step >> 2) * nbl2bit[encoded][3] +
|
||||
(step >> 3));
|
||||
*ssindex = *ssindex + indsft[(encoded & 7)];
|
||||
if (*ssindex < 0)
|
||||
*ssindex = 0;
|
||||
else if (*ssindex > 48)
|
||||
*ssindex = 48;
|
||||
return (diff);
|
||||
}
|
||||
|
||||
/*
|
||||
* Adpcm
|
||||
* Takes a signed linear signal and encodes it as ADPCM
|
||||
* For more information see http://support.dialogic.com/appnotes/adpcm.pdf
|
||||
*
|
||||
* Results:
|
||||
* Foo.
|
||||
*
|
||||
* Side effects:
|
||||
* signal gets updated with each pass.
|
||||
*/
|
||||
|
||||
static inline unsigned char
|
||||
adpcm (short csig, short *ssindex, short *signal)
|
||||
{
|
||||
short diff, step;
|
||||
unsigned char encoded;
|
||||
step = stpsz[*ssindex];
|
||||
/*
|
||||
* Clip csig if too large or too small
|
||||
*/
|
||||
|
||||
csig >>= 4;
|
||||
|
||||
diff = csig - *signal;
|
||||
|
||||
if (diff < 0)
|
||||
{
|
||||
encoded = 8;
|
||||
diff = -diff;
|
||||
}
|
||||
else
|
||||
encoded = 0;
|
||||
if (diff >= step)
|
||||
{
|
||||
encoded |= 4;
|
||||
diff -= step;
|
||||
}
|
||||
step >>= 1;
|
||||
if (diff >= step)
|
||||
{
|
||||
encoded |= 2;
|
||||
diff -= step;
|
||||
}
|
||||
step >>= 1;
|
||||
if (diff >= step)
|
||||
encoded |= 1;
|
||||
|
||||
*signal += decode (encoded, ssindex);
|
||||
return (encoded);
|
||||
}
|
||||
|
||||
/*
|
||||
* Private workspace for translating signed linear signals to ADPCM.
|
||||
*/
|
||||
|
||||
struct adpcm_encoder_pvt
|
||||
{
|
||||
struct ast_frame f;
|
||||
char offset[AST_FRIENDLY_OFFSET]; /* Space to build offset */
|
||||
short inbuf[BUFFER_SIZE]; /* Unencoded signed linear values */
|
||||
unsigned char outbuf[BUFFER_SIZE]; /* Encoded ADPCM, two nibbles to a word */
|
||||
short ssindex;
|
||||
short signal;
|
||||
int tail;
|
||||
};
|
||||
|
||||
/*
|
||||
* Private workspace for translating ADPCM signals to signed linear.
|
||||
*/
|
||||
|
||||
struct adpcm_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;
|
||||
};
|
||||
|
||||
/*
|
||||
* AdpcmToLin_New
|
||||
* Create a new instance of adpcm_decoder_pvt.
|
||||
*
|
||||
* Results:
|
||||
* Returns a pointer to the new instance.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*/
|
||||
|
||||
static struct ast_translator_pvt *
|
||||
adpcmtolin_new ()
|
||||
{
|
||||
struct adpcm_decoder_pvt *tmp;
|
||||
tmp = malloc (sizeof (struct adpcm_decoder_pvt));
|
||||
if (tmp)
|
||||
{
|
||||
memset(tmp, 0, sizeof(*tmp));
|
||||
tmp->tail = 0;
|
||||
localusecnt++;
|
||||
ast_update_use_count ();
|
||||
}
|
||||
return (struct ast_translator_pvt *) tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* LinToAdpcm_New
|
||||
* Create a new instance of adpcm_encoder_pvt.
|
||||
*
|
||||
* Results:
|
||||
* Returns a pointer to the new instance.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*/
|
||||
|
||||
static struct ast_translator_pvt *
|
||||
lintoadpcm_new ()
|
||||
{
|
||||
struct adpcm_encoder_pvt *tmp;
|
||||
tmp = malloc (sizeof (struct adpcm_encoder_pvt));
|
||||
if (tmp)
|
||||
{
|
||||
memset(tmp, 0, sizeof(*tmp));
|
||||
localusecnt++;
|
||||
ast_update_use_count ();
|
||||
tmp->tail = 0;
|
||||
}
|
||||
return (struct ast_translator_pvt *) tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* AdpcmToLin_FrameIn
|
||||
* Fill an input buffer with packed 4-bit ADPCM values if there is room
|
||||
* left.
|
||||
*
|
||||
* Results:
|
||||
* Foo
|
||||
*
|
||||
* Side effects:
|
||||
* tmp->tail is the number of packed values in the buffer.
|
||||
*/
|
||||
|
||||
static int
|
||||
adpcmtolin_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
|
||||
{
|
||||
struct adpcm_decoder_pvt *tmp = (struct adpcm_decoder_pvt *) pvt;
|
||||
int x;
|
||||
short signal;
|
||||
short ssindex;
|
||||
unsigned char *b;
|
||||
|
||||
if (f->datalen < 3) {
|
||||
ast_log(LOG_WARNING, "Didn't have at least three bytes of input\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((f->datalen - 3) * 4 > 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;
|
||||
ssindex = b[0];
|
||||
if (ssindex < 0)
|
||||
ssindex = 0;
|
||||
if (ssindex > 48)
|
||||
ssindex = 48;
|
||||
|
||||
signal = (b[1] << 8) | b[2];
|
||||
|
||||
for (x=3;x<f->datalen;x++) {
|
||||
signal += decode(b[x] >> 4, &ssindex);
|
||||
if (signal > 2047)
|
||||
signal = 2047;
|
||||
if (signal < -2048)
|
||||
signal = -2048;
|
||||
tmp->outbuf[tmp->tail++] = signal << 4;
|
||||
signal += decode(b[x] & 0x0f, &ssindex);
|
||||
if (signal > 2047)
|
||||
signal = 2047;
|
||||
if (signal < -2048)
|
||||
signal = -2048;
|
||||
tmp->outbuf[tmp->tail++] = signal << 4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* AdpcmToLin_FrameOut
|
||||
* Convert 4-bit ADPCM 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 *
|
||||
adpcmtolin_frameout (struct ast_translator_pvt *pvt)
|
||||
{
|
||||
struct adpcm_decoder_pvt *tmp = (struct adpcm_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;
|
||||
}
|
||||
|
||||
/*
|
||||
* LinToAdpcm_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
|
||||
lintoadpcm_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
|
||||
{
|
||||
struct adpcm_encoder_pvt *tmp = (struct adpcm_encoder_pvt *) pvt;
|
||||
|
||||
if ((tmp->tail + f->datalen / 2) < (sizeof (tmp->inbuf) / 2))
|
||||
{
|
||||
memcpy (&tmp->inbuf[tmp->tail], f->data, f->datalen);
|
||||
tmp->tail += f->datalen / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
ast_log (LOG_WARNING, "Out of buffer space\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* LinToAdpcm_FrameOut
|
||||
* Convert a buffer of raw 16-bit signed linear PCM to a buffer
|
||||
* of 4-bit ADPCM packed two to a byte (Big Endian).
|
||||
*
|
||||
* Results:
|
||||
* Foo
|
||||
*
|
||||
* Side effects:
|
||||
* Leftover inbuf data gets packed, tail gets updated.
|
||||
*/
|
||||
|
||||
static struct ast_frame *
|
||||
lintoadpcm_frameout (struct ast_translator_pvt *pvt)
|
||||
{
|
||||
struct adpcm_encoder_pvt *tmp = (struct adpcm_encoder_pvt *) pvt;
|
||||
unsigned char adpcm0, adpcm1;
|
||||
int i_max, i;
|
||||
|
||||
if (tmp->tail < 2) return NULL;
|
||||
|
||||
|
||||
i_max = (tmp->tail / 2) * 2;
|
||||
|
||||
tmp->outbuf[0] = tmp->ssindex & 0xff;
|
||||
tmp->outbuf[1] = (tmp->signal >> 8) & 0xff;
|
||||
tmp->outbuf[2] = (tmp->signal & 0xff);
|
||||
|
||||
for (i = 0; i < i_max; i+=2)
|
||||
{
|
||||
adpcm0 = adpcm(tmp->inbuf[i], &tmp->ssindex, &tmp->signal);
|
||||
adpcm1 = adpcm(tmp->inbuf[i+1], &tmp->ssindex, &tmp->signal);
|
||||
tmp->outbuf[i/2 + 3] = (adpcm0 << 4) | adpcm1;
|
||||
};
|
||||
|
||||
|
||||
tmp->f.frametype = AST_FRAME_VOICE;
|
||||
tmp->f.subclass = AST_FORMAT_ADPCM;
|
||||
tmp->f.timelen = i_max / 8;
|
||||
tmp->f.mallocd = 0;
|
||||
tmp->f.offset = AST_FRIENDLY_OFFSET;
|
||||
tmp->f.src = __PRETTY_FUNCTION__;
|
||||
tmp->f.data = tmp->outbuf;
|
||||
tmp->f.datalen = i_max / 2 + 3;
|
||||
|
||||
/*
|
||||
* If there is a signal left over (there should be no more than
|
||||
* one) move it to the beginning of the input buffer.
|
||||
*/
|
||||
|
||||
if (tmp->tail == i_max)
|
||||
tmp->tail = 0;
|
||||
else
|
||||
{
|
||||
tmp->inbuf[0] = tmp->inbuf[tmp->tail];
|
||||
tmp->tail = 1;
|
||||
}
|
||||
return &tmp->f;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* AdpcmToLin_Sample
|
||||
*/
|
||||
|
||||
static struct ast_frame *
|
||||
adpcmtolin_sample ()
|
||||
{
|
||||
static struct ast_frame f;
|
||||
f.frametype = AST_FRAME_VOICE;
|
||||
f.subclass = AST_FORMAT_ADPCM;
|
||||
f.datalen = sizeof (adpcm_slin_ex);
|
||||
f.timelen = sizeof(adpcm_slin_ex) / 4;
|
||||
f.mallocd = 0;
|
||||
f.offset = 0;
|
||||
f.src = __PRETTY_FUNCTION__;
|
||||
f.data = adpcm_slin_ex;
|
||||
return &f;
|
||||
}
|
||||
|
||||
/*
|
||||
* LinToAdpcm_Sample
|
||||
*/
|
||||
|
||||
static struct ast_frame *
|
||||
lintoadpcm_sample ()
|
||||
{
|
||||
static struct ast_frame f;
|
||||
f.frametype = AST_FRAME_VOICE;
|
||||
f.subclass = AST_FORMAT_SLINEAR;
|
||||
f.datalen = sizeof (slin_adpcm_ex);
|
||||
/* Assume 8000 Hz */
|
||||
f.timelen = sizeof (slin_adpcm_ex) / 16;
|
||||
f.mallocd = 0;
|
||||
f.offset = 0;
|
||||
f.src = __PRETTY_FUNCTION__;
|
||||
f.data = slin_adpcm_ex;
|
||||
return &f;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adpcm_Destroy
|
||||
* Destroys a private workspace.
|
||||
*
|
||||
* Results:
|
||||
* It's gone!
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*/
|
||||
|
||||
static void
|
||||
adpcm_destroy (struct ast_translator_pvt *pvt)
|
||||
{
|
||||
free (pvt);
|
||||
localusecnt--;
|
||||
ast_update_use_count ();
|
||||
}
|
||||
|
||||
/*
|
||||
* The complete translator for ADPCMToLin.
|
||||
*/
|
||||
|
||||
static struct ast_translator adpcmtolin = {
|
||||
"adpcmtolin",
|
||||
AST_FORMAT_ADPCM,
|
||||
AST_FORMAT_SLINEAR,
|
||||
adpcmtolin_new,
|
||||
adpcmtolin_framein,
|
||||
adpcmtolin_frameout,
|
||||
adpcm_destroy,
|
||||
/* NULL */
|
||||
adpcmtolin_sample
|
||||
};
|
||||
|
||||
/*
|
||||
* The complete translator for LinToADPCM.
|
||||
*/
|
||||
|
||||
static struct ast_translator lintoadpcm = {
|
||||
"lintoadpcm",
|
||||
AST_FORMAT_SLINEAR,
|
||||
AST_FORMAT_ADPCM,
|
||||
lintoadpcm_new,
|
||||
lintoadpcm_framein,
|
||||
lintoadpcm_frameout,
|
||||
adpcm_destroy,
|
||||
/* NULL */
|
||||
lintoadpcm_sample
|
||||
};
|
||||
|
||||
int
|
||||
unload_module (void)
|
||||
{
|
||||
int res;
|
||||
ast_pthread_mutex_lock (&localuser_lock);
|
||||
res = ast_unregister_translator (&lintoadpcm);
|
||||
if (!res)
|
||||
res = ast_unregister_translator (&adpcmtolin);
|
||||
if (localusecnt)
|
||||
res = -1;
|
||||
ast_pthread_mutex_unlock (&localuser_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
load_module (void)
|
||||
{
|
||||
int res;
|
||||
res = ast_register_translator (&adpcmtolin);
|
||||
if (!res)
|
||||
res = ast_register_translator (&lintoadpcm);
|
||||
else
|
||||
ast_unregister_translator (&adpcmtolin);
|
||||
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;
|
||||
}
|
||||
@@ -23,7 +23,6 @@
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <pthread.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
@@ -76,7 +75,7 @@ struct g723_encoder_pvt {
|
||||
/* Space to build offset */
|
||||
char offset[AST_FRIENDLY_OFFSET];
|
||||
/* Buffer for our outgoing frame */
|
||||
char outbuf[8000];
|
||||
char outbuf[24];
|
||||
/* Enough to store a full second */
|
||||
short buf[8000];
|
||||
int tail;
|
||||
@@ -174,72 +173,41 @@ static struct ast_frame *g723tolin_frameout(struct ast_translator_pvt *pvt)
|
||||
tmp->tail = 0;
|
||||
|
||||
#if 0
|
||||
/* Save the frames */
|
||||
{
|
||||
static int fd2 = -1;
|
||||
if (fd2 == -1) {
|
||||
fd2 = open("g723.example", O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
}
|
||||
write(fd2, tmp->f.data, tmp->f.datalen);
|
||||
/* Save a sample frame */
|
||||
{ static int samplefr = 0;
|
||||
if (samplefr == 80) {
|
||||
int fd;
|
||||
fd = open("g723.example", O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
write(fd, tmp->f.data, tmp->f.datalen);
|
||||
close(fd);
|
||||
}
|
||||
samplefr++;
|
||||
}
|
||||
#endif
|
||||
return &tmp->f;
|
||||
}
|
||||
|
||||
static int g723_len(unsigned char buf)
|
||||
{
|
||||
switch(buf & TYPE_MASK) {
|
||||
case TYPE_MASK:
|
||||
case TYPE_SILENCE:
|
||||
return 4;
|
||||
break;
|
||||
case TYPE_HIGH:
|
||||
return 24;
|
||||
break;
|
||||
case TYPE_LOW:
|
||||
return 20;
|
||||
break;
|
||||
default:
|
||||
ast_log(LOG_WARNING, "Badly encoded frame (%d)\n", buf & TYPE_MASK);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int g723tolin_framein(struct ast_translator_pvt *pvt, struct ast_frame *f)
|
||||
{
|
||||
struct g723_decoder_pvt *tmp = (struct g723_decoder_pvt *)pvt;
|
||||
int len = 0;
|
||||
int res;
|
||||
#ifdef ANNEX_B
|
||||
FLOAT tmpdata[Frame];
|
||||
int x;
|
||||
#endif
|
||||
while(len < f->datalen) {
|
||||
/* Assuming there's space left, decode into the current buffer at
|
||||
the tail location */
|
||||
res = g723_len(((unsigned char *)f->data + len)[0]);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Invalid data\n");
|
||||
return -1;
|
||||
}
|
||||
if (res + len > f->datalen) {
|
||||
ast_log(LOG_WARNING, "Measured length exceeds frame length\n");
|
||||
return -1;
|
||||
}
|
||||
if (tmp->tail + Frame < sizeof(tmp->buf)/2) {
|
||||
/* Assuming there's space left, decode into the current buffer at
|
||||
the tail location */
|
||||
if (tmp->tail + Frame < sizeof(tmp->buf)/2) {
|
||||
#ifdef ANNEX_B
|
||||
Decod(&tmp->dec, tmpdata, f->data + len, 0);
|
||||
for (x=0;x<Frame;x++)
|
||||
(tmp->buf + tmp->tail)[x] = (short)(tmpdata[x]);
|
||||
Decod(&tmp->dec, tmpdata, f->data, 0);
|
||||
for (x=0;x<Frame;x++)
|
||||
(tmp->buf + tmp->tail)[x] = (short)tmpdata[x];
|
||||
#else
|
||||
Decod(&tmp->dec, tmp->buf + tmp->tail, f->data + len, 0);
|
||||
Decod(&tmp->dec, tmp->buf + tmp->tail, f->data, 0);
|
||||
#endif
|
||||
tmp->tail+=Frame;
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Out of buffer space\n");
|
||||
return -1;
|
||||
}
|
||||
len += res;
|
||||
tmp->tail+=Frame;
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Out of buffer space\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -268,39 +236,43 @@ static struct ast_frame *lintog723_frameout(struct ast_translator_pvt *pvt)
|
||||
int x;
|
||||
FLOAT tmpdata[Frame];
|
||||
#endif
|
||||
int cnt=0;
|
||||
/* We can't work on anything less than a frame in size */
|
||||
if (tmp->tail < Frame)
|
||||
return NULL;
|
||||
/* Encode a frame of data */
|
||||
#ifdef ANNEX_B
|
||||
for (x=0;x<Frame;x++)
|
||||
tmpdata[x] = tmp->buf[x];
|
||||
Coder(&tmp->cod, tmpdata, tmp->outbuf);
|
||||
#else
|
||||
Coder(&tmp->cod, tmp->buf, tmp->outbuf);
|
||||
#endif
|
||||
tmp->f.frametype = AST_FRAME_VOICE;
|
||||
tmp->f.subclass = AST_FORMAT_G723_1;
|
||||
/* Assume 8000 Hz */
|
||||
tmp->f.timelen = 30;
|
||||
tmp->f.mallocd = 0;
|
||||
tmp->f.offset = AST_FRIENDLY_OFFSET;
|
||||
tmp->f.src = __PRETTY_FUNCTION__;
|
||||
tmp->f.timelen = 0;
|
||||
tmp->f.mallocd = 0;
|
||||
while(tmp->tail >= Frame) {
|
||||
/* Encode a frame of data */
|
||||
if (cnt + 24 >= sizeof(tmp->outbuf)) {
|
||||
ast_log(LOG_WARNING, "Out of buffer space\n");
|
||||
return NULL;
|
||||
}
|
||||
#ifdef ANNEX_B
|
||||
for (x=0;x<Frame;x++)
|
||||
tmpdata[x] = tmp->buf[x];
|
||||
Coder(&tmp->cod, tmpdata, tmp->outbuf + cnt);
|
||||
#else
|
||||
Coder(&tmp->cod, tmp->buf, tmp->outbuf + cnt);
|
||||
#endif
|
||||
/* Assume 8000 Hz */
|
||||
tmp->f.timelen += 30;
|
||||
cnt += g723_len(tmp->outbuf[0]);
|
||||
tmp->tail -= Frame;
|
||||
/* Move the data at the end of the buffer to the front */
|
||||
if (tmp->tail)
|
||||
memmove(tmp->buf, tmp->buf + Frame, tmp->tail * 2);
|
||||
}
|
||||
tmp->f.datalen = cnt;
|
||||
tmp->f.data = tmp->outbuf;
|
||||
switch(tmp->outbuf[0] & TYPE_MASK) {
|
||||
case TYPE_MASK:
|
||||
case TYPE_SILENCE:
|
||||
tmp->f.datalen = 4;
|
||||
break;
|
||||
case TYPE_HIGH:
|
||||
tmp->f.datalen = 24;
|
||||
break;
|
||||
case TYPE_LOW:
|
||||
tmp->f.datalen = 20;
|
||||
break;
|
||||
default:
|
||||
ast_log(LOG_WARNING, "Badly encoded frame (%d)\n", tmp->outbuf[0] & TYPE_MASK);
|
||||
}
|
||||
tmp->tail -= Frame;
|
||||
/* Move the data at the end of the buffer to the front */
|
||||
if (tmp->tail)
|
||||
memmove(tmp->buf, tmp->buf + Frame, tmp->tail * 2);
|
||||
#if 0
|
||||
/* Save to a g723 sample output file... */
|
||||
{
|
||||
@@ -358,13 +330,13 @@ static struct ast_translator lintog723 =
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
ast_pthread_mutex_lock(&localuser_lock);
|
||||
pthread_mutex_lock(&localuser_lock);
|
||||
res = ast_unregister_translator(&lintog723);
|
||||
if (!res)
|
||||
res = ast_unregister_translator(&g723tolin);
|
||||
if (localusecnt)
|
||||
res = -1;
|
||||
ast_pthread_mutex_unlock(&localuser_lock);
|
||||
pthread_mutex_unlock(&localuser_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -390,8 +362,3 @@ int usecount(void)
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <pthread.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
@@ -48,7 +47,7 @@ struct ast_translator_pvt {
|
||||
/* Space to build offset */
|
||||
char offset[AST_FRIENDLY_OFFSET];
|
||||
/* Buffer for our outgoing frame */
|
||||
short outbuf[8000];
|
||||
gsm_frame outbuf;
|
||||
/* Enough to store a full second */
|
||||
short buf[8000];
|
||||
int tail;
|
||||
@@ -119,29 +118,34 @@ static struct ast_frame *gsmtolin_frameout(struct ast_translator_pvt *tmp)
|
||||
/* Reset tail pointer */
|
||||
tmp->tail = 0;
|
||||
|
||||
#if 0
|
||||
/* Save a sample frame */
|
||||
{ static int samplefr = 0;
|
||||
if (samplefr == 80) {
|
||||
int fd;
|
||||
fd = open("gsm.example", O_WRONLY | O_CREAT, 0644);
|
||||
write(fd, tmp->f.data, tmp->f.datalen);
|
||||
close(fd);
|
||||
}
|
||||
samplefr++;
|
||||
}
|
||||
#endif
|
||||
return &tmp->f;
|
||||
}
|
||||
|
||||
static int gsmtolin_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
|
||||
{
|
||||
/* Assuming there's space left, decode into the current buffer at
|
||||
the tail location. Read in as many frames as there are */
|
||||
int x;
|
||||
if (f->datalen % 33) {
|
||||
ast_log(LOG_WARNING, "Huh? A GSM frame that isn't a multiple of 33 bytes long from %s (%d)?\n", f->src, f->datalen);
|
||||
return -1;
|
||||
}
|
||||
for (x=0;x<f->datalen;x+=33) {
|
||||
if (tmp->tail + 160 < sizeof(tmp->buf)/2) {
|
||||
if (gsm_decode(tmp->gsm, f->data + x, tmp->buf + tmp->tail)) {
|
||||
ast_log(LOG_WARNING, "Invalid GSM data\n");
|
||||
return -1;
|
||||
}
|
||||
tmp->tail+=160;
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Out of buffer space\n");
|
||||
the tail location */
|
||||
if (tmp->tail + 160 < sizeof(tmp->buf)/2) {
|
||||
if (gsm_decode(tmp->gsm, f->data, tmp->buf + tmp->tail)) {
|
||||
ast_log(LOG_WARNING, "Invalid GSM data\n");
|
||||
return -1;
|
||||
}
|
||||
tmp->tail+=160;
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Out of buffer space\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -152,7 +156,7 @@ static int lintogsm_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
|
||||
/* XXX We should look at how old the rest of our stream is, and if it
|
||||
is too old, then we should overwrite it entirely, otherwise we can
|
||||
get artifacts of earlier talk that do not belong */
|
||||
if (tmp->tail + f->datalen/2 < sizeof(tmp->buf) / 2) {
|
||||
if (tmp->tail + f->datalen < sizeof(tmp->buf) / 2) {
|
||||
memcpy((tmp->buf + tmp->tail), f->data, f->datalen);
|
||||
tmp->tail += f->datalen/2;
|
||||
} else {
|
||||
@@ -164,32 +168,36 @@ static int lintogsm_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
|
||||
|
||||
static struct ast_frame *lintogsm_frameout(struct ast_translator_pvt *tmp)
|
||||
{
|
||||
int x=0;
|
||||
/* We can't work on anything less than a frame in size */
|
||||
if (tmp->tail < 160)
|
||||
return NULL;
|
||||
/* Encode a frame of data */
|
||||
gsm_encode(tmp->gsm, tmp->buf, tmp->outbuf);
|
||||
tmp->f.frametype = AST_FRAME_VOICE;
|
||||
tmp->f.subclass = AST_FORMAT_GSM;
|
||||
tmp->f.datalen = 33;
|
||||
/* Assume 8000 Hz -- 20 ms */
|
||||
tmp->f.timelen = 20;
|
||||
tmp->f.mallocd = 0;
|
||||
tmp->f.offset = AST_FRIENDLY_OFFSET;
|
||||
tmp->f.src = __PRETTY_FUNCTION__;
|
||||
tmp->f.data = tmp->outbuf;
|
||||
while(tmp->tail >= 160) {
|
||||
if ((x+1) * 33 >= sizeof(tmp->outbuf)) {
|
||||
ast_log(LOG_WARNING, "Out of buffer space\n");
|
||||
break;
|
||||
}
|
||||
/* Encode a frame of data */
|
||||
gsm_encode(tmp->gsm, tmp->buf, ((gsm_byte *) tmp->outbuf) + (x * 33));
|
||||
/* Assume 8000 Hz -- 20 ms */
|
||||
tmp->tail -= 160;
|
||||
/* Move the data at the end of the buffer to the front */
|
||||
if (tmp->tail)
|
||||
memmove(tmp->buf, tmp->buf + 160, tmp->tail * 2);
|
||||
x++;
|
||||
tmp->tail -= 160;
|
||||
/* Move the data at the end of the buffer to the front */
|
||||
if (tmp->tail)
|
||||
memmove(tmp->buf, tmp->buf + 160, tmp->tail * 2);
|
||||
#if 0
|
||||
/* Save a sample frame */
|
||||
{ static int samplefr = 0;
|
||||
if (samplefr == 0) {
|
||||
int fd;
|
||||
fd = open("gsm.example", O_WRONLY | O_CREAT, 0644);
|
||||
write(fd, tmp->f.data, tmp->f.datalen);
|
||||
close(fd);
|
||||
}
|
||||
samplefr++;
|
||||
}
|
||||
tmp->f.datalen = x * 33;
|
||||
tmp->f.timelen = x * 20;
|
||||
#endif
|
||||
return &tmp->f;
|
||||
}
|
||||
|
||||
@@ -222,13 +230,13 @@ static struct ast_translator lintogsm =
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
ast_pthread_mutex_lock(&localuser_lock);
|
||||
pthread_mutex_lock(&localuser_lock);
|
||||
res = ast_unregister_translator(&lintogsm);
|
||||
if (!res)
|
||||
res = ast_unregister_translator(&gsmtolin);
|
||||
if (localusecnt)
|
||||
res = -1;
|
||||
ast_pthread_mutex_unlock(&localuser_lock);
|
||||
pthread_mutex_unlock(&localuser_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -254,8 +262,3 @@ int usecount(void)
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <pthread.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
@@ -56,7 +55,7 @@ struct ast_translator_pvt {
|
||||
/* Space to build offset */
|
||||
char offset[AST_FRIENDLY_OFFSET];
|
||||
/* Buffer for our outgoing frame */
|
||||
short outbuf[8000];
|
||||
short outbuf[LPC10_SAMPLES_PER_FRAME];
|
||||
/* Enough to store a full second */
|
||||
short buf[8000];
|
||||
int tail;
|
||||
@@ -198,32 +197,26 @@ static int lpc10tolin_framein(struct ast_translator_pvt *tmp, struct ast_frame *
|
||||
/* Assuming there's space left, decode into the current buffer at
|
||||
the tail location */
|
||||
int x;
|
||||
int len=0;
|
||||
float tmpbuf[LPC10_SAMPLES_PER_FRAME];
|
||||
short *sd;
|
||||
INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME];
|
||||
while(len + LPC10_BYTES_IN_COMPRESSED_FRAME <= f->datalen) {
|
||||
if (tmp->tail + LPC10_SAMPLES_PER_FRAME < sizeof(tmp->buf)/2) {
|
||||
sd = tmp->buf + tmp->tail;
|
||||
extract_bits(bits, f->data + len);
|
||||
if (lpc10_decode(bits, tmpbuf, tmp->lpc10.dec)) {
|
||||
ast_log(LOG_WARNING, "Invalid lpc10 data\n");
|
||||
return -1;
|
||||
}
|
||||
for (x=0;x<LPC10_SAMPLES_PER_FRAME;x++) {
|
||||
/* Convert to a real between -1.0 and 1.0 */
|
||||
sd[x] = 32768.0 * tmpbuf[x];
|
||||
}
|
||||
|
||||
tmp->tail+=LPC10_SAMPLES_PER_FRAME;
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Out of buffer space\n");
|
||||
if (tmp->tail + LPC10_SAMPLES_PER_FRAME < sizeof(tmp->buf)/2) {
|
||||
sd = tmp->buf + tmp->tail;
|
||||
extract_bits(bits, f->data);
|
||||
if (lpc10_decode(bits, tmpbuf, tmp->lpc10.dec)) {
|
||||
ast_log(LOG_WARNING, "Invalid lpc10 data\n");
|
||||
return -1;
|
||||
}
|
||||
len += LPC10_BYTES_IN_COMPRESSED_FRAME;
|
||||
for (x=0;x<LPC10_SAMPLES_PER_FRAME;x++) {
|
||||
/* Convert to a real between -1.0 and 1.0 */
|
||||
sd[x] = 32768.0 * tmpbuf[x];
|
||||
}
|
||||
|
||||
tmp->tail+=LPC10_SAMPLES_PER_FRAME;
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Out of buffer space\n");
|
||||
return -1;
|
||||
}
|
||||
if (len != f->datalen)
|
||||
printf("Decoded %d, expected %d\n", len, f->datalen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -246,48 +239,35 @@ static int lintolpc10_framein(struct ast_translator_pvt *tmp, struct ast_frame *
|
||||
static struct ast_frame *lintolpc10_frameout(struct ast_translator_pvt *tmp)
|
||||
{
|
||||
int x;
|
||||
int consumed = 0;
|
||||
float tmpbuf[LPC10_SAMPLES_PER_FRAME];
|
||||
INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME];
|
||||
/* We can't work on anything less than a frame in size */
|
||||
if (tmp->tail < LPC10_SAMPLES_PER_FRAME)
|
||||
return NULL;
|
||||
/* Start with an empty frame */
|
||||
tmp->f.timelen = 0;
|
||||
tmp->f.datalen = 0;
|
||||
/* Encode a frame of data */
|
||||
for (x=0;x<LPC10_SAMPLES_PER_FRAME;x++) {
|
||||
tmpbuf[x] = (float)tmp->buf[x] / 32768.0;
|
||||
}
|
||||
lpc10_encode(tmpbuf, bits, tmp->lpc10.enc);
|
||||
build_bits((unsigned char *)tmp->outbuf, bits);
|
||||
tmp->f.frametype = AST_FRAME_VOICE;
|
||||
tmp->f.subclass = AST_FORMAT_LPC10;
|
||||
while(tmp->tail >= LPC10_SAMPLES_PER_FRAME) {
|
||||
if (tmp->f.datalen + LPC10_BYTES_IN_COMPRESSED_FRAME > sizeof(tmp->outbuf)) {
|
||||
ast_log(LOG_WARNING, "Out of buffer space\n");
|
||||
return NULL;
|
||||
}
|
||||
/* Encode a frame of data */
|
||||
for (x=0;x<LPC10_SAMPLES_PER_FRAME;x++) {
|
||||
tmpbuf[x] = (float)tmp->buf[x+consumed] / 32768.0;
|
||||
}
|
||||
lpc10_encode(tmpbuf, bits, tmp->lpc10.enc);
|
||||
build_bits(((unsigned char *)tmp->outbuf) + tmp->f.datalen, bits);
|
||||
tmp->f.datalen += LPC10_BYTES_IN_COMPRESSED_FRAME;
|
||||
tmp->f.timelen += 22;
|
||||
/* We alternate between 22 and 23 ms to simulate 22.5 ms */
|
||||
tmp->f.timelen += tmp->longer;
|
||||
/* Use one of the two left over bits to record if this is a 22 or 23 ms frame...
|
||||
important for IAX use */
|
||||
tmp->longer = 1 - tmp->longer;
|
||||
#if 0 /* what the heck was this for? */
|
||||
((char *)(tmp->f.data))[consumed - 1] |= tmp->longer;
|
||||
#endif
|
||||
tmp->tail -= LPC10_SAMPLES_PER_FRAME;
|
||||
consumed += LPC10_SAMPLES_PER_FRAME;
|
||||
}
|
||||
tmp->f.datalen = LPC10_BYTES_IN_COMPRESSED_FRAME;
|
||||
tmp->f.timelen = 22;
|
||||
/* We alternate between 22 and 23 ms to simulate 22.5 ms */
|
||||
tmp->f.timelen += tmp->longer;
|
||||
/* Use one of the two left over bits to record if this is a 22 or 23 ms frame...
|
||||
important for IAX use */
|
||||
tmp->longer = 1 - tmp->longer;
|
||||
tmp->f.mallocd = 0;
|
||||
tmp->f.offset = AST_FRIENDLY_OFFSET;
|
||||
tmp->f.src = __PRETTY_FUNCTION__;
|
||||
tmp->f.data = tmp->outbuf;
|
||||
((char *)(tmp->f.data))[LPC10_BYTES_IN_COMPRESSED_FRAME - 1] |= tmp->longer;
|
||||
tmp->tail -= LPC10_SAMPLES_PER_FRAME;
|
||||
/* Move the data at the end of the buffer to the front */
|
||||
if (tmp->tail)
|
||||
memmove(tmp->buf, tmp->buf + consumed, tmp->tail * 2);
|
||||
memmove(tmp->buf, tmp->buf + LPC10_SAMPLES_PER_FRAME, tmp->tail * 2);
|
||||
#if 0
|
||||
/* Save a sample frame */
|
||||
{ static int samplefr = 0;
|
||||
@@ -334,13 +314,13 @@ static struct ast_translator lintolpc10 =
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
ast_pthread_mutex_lock(&localuser_lock);
|
||||
pthread_mutex_lock(&localuser_lock);
|
||||
res = ast_unregister_translator(&lintolpc10);
|
||||
if (!res)
|
||||
res = ast_unregister_translator(&lpc10tolin);
|
||||
if (localusecnt)
|
||||
res = -1;
|
||||
ast_pthread_mutex_unlock(&localuser_lock);
|
||||
pthread_mutex_unlock(&localuser_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -366,8 +346,3 @@ int usecount(void)
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <pthread.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
@@ -109,30 +108,40 @@ static struct ast_frame *mp3tolin_sample()
|
||||
|
||||
static struct ast_frame *mp3tolin_frameout(struct ast_translator_pvt *tmp)
|
||||
{
|
||||
int sent;
|
||||
if (!tmp->tail)
|
||||
return NULL;
|
||||
sent = tmp->tail;
|
||||
if (sent > MAX_OUT_FRAME/2)
|
||||
sent = MAX_OUT_FRAME/2;
|
||||
/* Signed linear is no particular frame size, so just send whatever
|
||||
we have in the buffer in one lump sum */
|
||||
tmp->f.frametype = AST_FRAME_VOICE;
|
||||
tmp->f.subclass = AST_FORMAT_SLINEAR;
|
||||
tmp->f.datalen = tmp->tail * 2;
|
||||
tmp->f.datalen = sent * 2;
|
||||
/* Assume 8000 Hz */
|
||||
tmp->f.timelen = tmp->tail / 8;
|
||||
tmp->f.timelen = sent / 8;
|
||||
tmp->f.mallocd = 0;
|
||||
tmp->f.offset = AST_FRIENDLY_OFFSET;
|
||||
tmp->f.src = __PRETTY_FUNCTION__;
|
||||
tmp->f.data = tmp->buf;
|
||||
memcpy(tmp->outbuf, tmp->buf, tmp->tail * 2);
|
||||
tmp->f.data = tmp->outbuf;
|
||||
/* Reset tail pointer */
|
||||
tmp->tail = 0;
|
||||
tmp->tail -= sent;
|
||||
if (tmp->tail)
|
||||
memmove(tmp->buf, tmp->buf + sent, tmp->tail * 2);
|
||||
|
||||
#if 0
|
||||
/* Save a sample frame */
|
||||
{
|
||||
static int fd = -1;
|
||||
if (fd < 0)
|
||||
fd = open("mp3out.raw", O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
{ static int samplefr = 0;
|
||||
if (samplefr == 80) {
|
||||
int fd;
|
||||
fd = open("mp3.example", O_WRONLY | O_CREAT, 0644);
|
||||
write(fd, tmp->f.data, tmp->f.datalen);
|
||||
close(fd);
|
||||
}
|
||||
samplefr++;
|
||||
}
|
||||
#endif
|
||||
return &tmp->f;
|
||||
}
|
||||
@@ -286,11 +295,11 @@ static struct ast_translator mp3tolin =
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
ast_pthread_mutex_lock(&localuser_lock);
|
||||
pthread_mutex_lock(&localuser_lock);
|
||||
res = ast_unregister_translator(&mp3tolin);
|
||||
if (localusecnt)
|
||||
res = -1;
|
||||
ast_pthread_mutex_unlock(&localuser_lock);
|
||||
pthread_mutex_unlock(&localuser_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -312,8 +321,3 @@ int usecount(void)
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
@@ -1,378 +0,0 @@
|
||||
/* codec_ulaw.c - translate between signed linear and ulaw
|
||||
*
|
||||
* 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/logger.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/channel.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 = PTHREAD_MUTEX_INITIALIZER;
|
||||
static int localusecnt = 0;
|
||||
|
||||
static char *tdesc = "Mu-law Coder/Decoder";
|
||||
|
||||
/* Sample frame data */
|
||||
|
||||
#include "slin_ulaw_ex.h"
|
||||
#include "ulaw_slin_ex.h"
|
||||
|
||||
/*
|
||||
* Private workspace for translating signed linear signals to ulaw.
|
||||
*/
|
||||
|
||||
struct ulaw_encoder_pvt
|
||||
{
|
||||
struct ast_frame f;
|
||||
char offset[AST_FRIENDLY_OFFSET]; /* Space to build offset */
|
||||
unsigned char outbuf[BUFFER_SIZE]; /* Encoded ulaw, two nibbles to a word */
|
||||
int tail;
|
||||
};
|
||||
|
||||
/*
|
||||
* Private workspace for translating ulaw signals to signed linear.
|
||||
*/
|
||||
|
||||
struct ulaw_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;
|
||||
};
|
||||
|
||||
/*
|
||||
* ulawToLin_New
|
||||
* Create a new instance of ulaw_decoder_pvt.
|
||||
*
|
||||
* Results:
|
||||
* Returns a pointer to the new instance.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*/
|
||||
|
||||
static struct ast_translator_pvt *
|
||||
ulawtolin_new ()
|
||||
{
|
||||
struct ulaw_decoder_pvt *tmp;
|
||||
tmp = malloc (sizeof (struct ulaw_decoder_pvt));
|
||||
if (tmp)
|
||||
{
|
||||
memset(tmp, 0, sizeof(*tmp));
|
||||
tmp->tail = 0;
|
||||
localusecnt++;
|
||||
ast_update_use_count ();
|
||||
}
|
||||
return (struct ast_translator_pvt *) tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* LinToulaw_New
|
||||
* Create a new instance of ulaw_encoder_pvt.
|
||||
*
|
||||
* Results:
|
||||
* Returns a pointer to the new instance.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*/
|
||||
|
||||
static struct ast_translator_pvt *
|
||||
lintoulaw_new ()
|
||||
{
|
||||
struct ulaw_encoder_pvt *tmp;
|
||||
tmp = malloc (sizeof (struct ulaw_encoder_pvt));
|
||||
if (tmp)
|
||||
{
|
||||
memset(tmp, 0, sizeof(*tmp));
|
||||
localusecnt++;
|
||||
ast_update_use_count ();
|
||||
tmp->tail = 0;
|
||||
}
|
||||
return (struct ast_translator_pvt *) tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* ulawToLin_FrameIn
|
||||
* Fill an input buffer with packed 4-bit ulaw values if there is room
|
||||
* left.
|
||||
*
|
||||
* Results:
|
||||
* Foo
|
||||
*
|
||||
* Side effects:
|
||||
* tmp->tail is the number of packed values in the buffer.
|
||||
*/
|
||||
|
||||
static int
|
||||
ulawtolin_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
|
||||
{
|
||||
struct ulaw_decoder_pvt *tmp = (struct ulaw_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_mulaw[b[x]];
|
||||
|
||||
tmp->tail += f->datalen;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ulawToLin_FrameOut
|
||||
* Convert 4-bit ulaw 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 *
|
||||
ulawtolin_frameout (struct ast_translator_pvt *pvt)
|
||||
{
|
||||
struct ulaw_decoder_pvt *tmp = (struct ulaw_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;
|
||||
}
|
||||
|
||||
/*
|
||||
* LinToulaw_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
|
||||
lintoulaw_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
|
||||
{
|
||||
struct ulaw_encoder_pvt *tmp = (struct ulaw_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_lin2mu[s[x]+32768];
|
||||
tmp->tail += f->datalen/2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* LinToulaw_FrameOut
|
||||
* Convert a buffer of raw 16-bit signed linear PCM to a buffer
|
||||
* of 4-bit ulaw packed two to a byte (Big Endian).
|
||||
*
|
||||
* Results:
|
||||
* Foo
|
||||
*
|
||||
* Side effects:
|
||||
* Leftover inbuf data gets packed, tail gets updated.
|
||||
*/
|
||||
|
||||
static struct ast_frame *
|
||||
lintoulaw_frameout (struct ast_translator_pvt *pvt)
|
||||
{
|
||||
struct ulaw_encoder_pvt *tmp = (struct ulaw_encoder_pvt *) pvt;
|
||||
|
||||
if (tmp->tail) {
|
||||
tmp->f.frametype = AST_FRAME_VOICE;
|
||||
tmp->f.subclass = AST_FORMAT_ULAW;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ulawToLin_Sample
|
||||
*/
|
||||
|
||||
static struct ast_frame *
|
||||
ulawtolin_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;
|
||||
}
|
||||
|
||||
/*
|
||||
* LinToulaw_Sample
|
||||
*/
|
||||
|
||||
static struct ast_frame *
|
||||
lintoulaw_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;
|
||||
}
|
||||
|
||||
/*
|
||||
* ulaw_Destroy
|
||||
* Destroys a private workspace.
|
||||
*
|
||||
* Results:
|
||||
* It's gone!
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*/
|
||||
|
||||
static void
|
||||
ulaw_destroy (struct ast_translator_pvt *pvt)
|
||||
{
|
||||
free (pvt);
|
||||
localusecnt--;
|
||||
ast_update_use_count ();
|
||||
}
|
||||
|
||||
/*
|
||||
* The complete translator for ulawToLin.
|
||||
*/
|
||||
|
||||
static struct ast_translator ulawtolin = {
|
||||
"ulawtolin",
|
||||
AST_FORMAT_ULAW,
|
||||
AST_FORMAT_SLINEAR,
|
||||
ulawtolin_new,
|
||||
ulawtolin_framein,
|
||||
ulawtolin_frameout,
|
||||
ulaw_destroy,
|
||||
/* NULL */
|
||||
ulawtolin_sample
|
||||
};
|
||||
|
||||
/*
|
||||
* The complete translator for LinToulaw.
|
||||
*/
|
||||
|
||||
static struct ast_translator lintoulaw = {
|
||||
"lintoulaw",
|
||||
AST_FORMAT_SLINEAR,
|
||||
AST_FORMAT_ULAW,
|
||||
lintoulaw_new,
|
||||
lintoulaw_framein,
|
||||
lintoulaw_frameout,
|
||||
ulaw_destroy,
|
||||
/* NULL */
|
||||
lintoulaw_sample
|
||||
};
|
||||
|
||||
int
|
||||
unload_module (void)
|
||||
{
|
||||
int res;
|
||||
ast_pthread_mutex_lock (&localuser_lock);
|
||||
res = ast_unregister_translator (&lintoulaw);
|
||||
if (!res)
|
||||
res = ast_unregister_translator (&ulawtolin);
|
||||
if (localusecnt)
|
||||
res = -1;
|
||||
ast_pthread_mutex_unlock (&localuser_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
load_module (void)
|
||||
{
|
||||
int res;
|
||||
res = ast_register_translator (&ulawtolin);
|
||||
if (!res)
|
||||
res = ast_register_translator (&lintoulaw);
|
||||
else
|
||||
ast_unregister_translator (&ulawtolin);
|
||||
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;
|
||||
}
|
||||
@@ -7,11 +7,11 @@
|
||||
SASR = -DSASR
|
||||
######### Define SASR if >> is a signed arithmetic shift (-1 >> 1 == -1)
|
||||
|
||||
#MULHACK = -DUSE_FLOAT_MUL
|
||||
MULHACK = -DUSE_FLOAT_MUL
|
||||
######### Define this if your host multiplies floats faster than integers,
|
||||
######### e.g. on a SPARCstation.
|
||||
|
||||
#FAST = -DFAST
|
||||
FAST = -DFAST
|
||||
######### Define together with USE_FLOAT_MUL to enable the GSM library's
|
||||
######### approximation option for incorrect, but good-enough results.
|
||||
|
||||
@@ -30,17 +30,6 @@ WAV49 = -DWAV49
|
||||
######### define this, and read about the GSM_OPT_WAV49 option in the
|
||||
######### manual page on gsm_option(3).
|
||||
|
||||
K6OPT = -DK6OPT
|
||||
#K6OPT =
|
||||
######### Define to enable MMXTM optimizations for x86 architecture CPU's
|
||||
######### which support MMX instructions. This should be newer pentiums,
|
||||
######### ppro's, etc, as well as the AMD K6 and K7. The compile will
|
||||
######### probably require gcc.
|
||||
|
||||
PG =
|
||||
#PG = -g -pg
|
||||
######### Profiling flags. If you don't know what that means, leave it blank.
|
||||
|
||||
# Choose a compiler. The code works both with ANSI and K&R-C.
|
||||
# Use -DNeedFunctionPrototypes to compile with, -UNeedFunctionPrototypes to
|
||||
# compile without, function prototypes in the header files.
|
||||
@@ -54,7 +43,7 @@ PG =
|
||||
# CC = /usr/lang/acc
|
||||
# CCFLAGS = -c -O
|
||||
|
||||
CC = gcc -ansi -pedantic -O6 -mpentium -fschedule-insns2 -fomit-frame-pointer
|
||||
CC = gcc -ansi -pedantic
|
||||
CCFLAGS += -c -DNeedFunctionPrototypes=1 -finline-functions -funroll-loops
|
||||
|
||||
LD = $(CC)
|
||||
@@ -137,21 +126,20 @@ INC = $(ROOT)/inc
|
||||
|
||||
# Flags
|
||||
|
||||
DEBUG = -DNDEBUG
|
||||
# DEBUG = -DNDEBUG
|
||||
######### Remove -DNDEBUG to enable assertions.
|
||||
|
||||
CFLAGS = $(PG) $(CCFLAGS) $(SASR) $(DEBUG) $(MULHACK) $(FAST) \
|
||||
$(LTP_CUT) $(WAV49) $(K6OPT) $(CCINC) -I$(INC)
|
||||
CFLAGS = $(CCFLAGS) $(SASR) $(DEBUG) $(MULHACK) $(FAST) $(LTP_CUT) \
|
||||
$(WAV49) $(CCINC) -I$(INC)
|
||||
######### It's $(CC) $(CFLAGS)
|
||||
|
||||
LFLAGS = $(PG) $(LDFLAGS) $(LDINC)
|
||||
LFLAGS = $(LDFLAGS) $(LDINC)
|
||||
######### It's $(LD) $(LFLAGS)
|
||||
|
||||
|
||||
# Targets
|
||||
|
||||
LIBGSM = $(LIB)/libgsm.a
|
||||
LIBGSMSO= $(LIB)/libgsm.so
|
||||
|
||||
TOAST = $(BIN)/toast
|
||||
UNTOAST = $(BIN)/untoast
|
||||
@@ -175,7 +163,6 @@ GSM_SOURCES = $(SRC)/add.c \
|
||||
$(SRC)/code.c \
|
||||
$(SRC)/debug.c \
|
||||
$(SRC)/decode.c \
|
||||
$(SRC)/k6opt.s \
|
||||
$(SRC)/long_term.c \
|
||||
$(SRC)/lpc.c \
|
||||
$(SRC)/preprocess.c \
|
||||
@@ -220,7 +207,6 @@ GSM_OBJECTS = $(SRC)/add.o \
|
||||
$(SRC)/code.o \
|
||||
$(SRC)/debug.o \
|
||||
$(SRC)/decode.o \
|
||||
$(SRC)/k6opt.o \
|
||||
$(SRC)/long_term.o \
|
||||
$(SRC)/lpc.o \
|
||||
$(SRC)/preprocess.o \
|
||||
@@ -293,7 +279,7 @@ TOAST_INSTALL_TARGETS = \
|
||||
|
||||
# Target rules
|
||||
|
||||
all: $(LIBGSM) $(LIBGSMSO) $(TOAST) $(TCAT) $(UNTOAST)
|
||||
all: $(LIBGSM) $(TOAST) $(TCAT) $(UNTOAST)
|
||||
@-echo $(ROOT): Done.
|
||||
|
||||
tst: $(TST)/lin2cod $(TST)/cod2lin $(TOAST) $(TST)/test-result
|
||||
@@ -313,11 +299,6 @@ install: toastinstall gsminstall
|
||||
|
||||
# The basic API: libgsm
|
||||
|
||||
$(LIBGSMSO): $(LIB) $(GSM_OBJECTS)
|
||||
$(LD) -o $@.1.0.10 -shared -Xlinker -soname -Xlinker libgsm.so.1 $(GSM_OBJECTS) -lc
|
||||
ln -fs libgsm.so.1.0.10 lib/libgsm.so.1
|
||||
ln -fs libgsm.so.1.0.10 lib/libgsm.so
|
||||
|
||||
$(LIBGSM): $(LIB) $(GSM_OBJECTS)
|
||||
-rm $(RMFLAGS) $(LIBGSM)
|
||||
$(AR) $(ARFLAGS) $(LIBGSM) $(GSM_OBJECTS)
|
||||
@@ -327,15 +308,15 @@ $(LIBGSM): $(LIB) $(GSM_OBJECTS)
|
||||
# Toast, Untoast and Tcat -- the compress-like frontends to gsm.
|
||||
|
||||
$(TOAST): $(BIN) $(TOAST_OBJECTS) $(LIBGSM)
|
||||
$(LD) $(LFLAGS) -o $(TOAST) $(TOAST_OBJECTS) $(LIBGSMSO) $(LDLIB)
|
||||
$(LD) $(LFLAGS) -o $(TOAST) $(TOAST_OBJECTS) $(LIBGSM) $(LDLIB)
|
||||
|
||||
$(UNTOAST): $(BIN) $(TOAST)
|
||||
-rm $(RMFLAGS) $(UNTOAST)
|
||||
$(LN) toast $(UNTOAST)
|
||||
$(LN) $(TOAST) $(UNTOAST)
|
||||
|
||||
$(TCAT): $(BIN) $(TOAST)
|
||||
-rm $(RMFLAGS) $(TCAT)
|
||||
$(LN) toast $(TCAT)
|
||||
$(LN) $(TOAST) $(TCAT)
|
||||
|
||||
|
||||
# The local bin and lib directories
|
||||
|
||||
@@ -98,44 +98,6 @@ extern word gsm_asr P((word a, int n));
|
||||
# define GSM_L_MULT(a, b) /* word a, word b */ \
|
||||
(((longword)(a) * (longword)(b)) << 1)
|
||||
|
||||
#if defined(__GNUC__) && defined(__i386__)
|
||||
|
||||
static __inline__ int GSM_L_ADD(int a, int b)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
|
||||
"addl %2,%0; jno 0f; movl $0x7fffffff,%0; adcl $0,%0; 0:"
|
||||
: "=r" (a)
|
||||
: "0" (a), "ir" (b)
|
||||
: "cc"
|
||||
);
|
||||
return(a);
|
||||
}
|
||||
|
||||
static __inline__ short GSM_ADD(short a, short b)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"addw %2,%0; jno 0f; movw $0x7fff,%0; adcw $0,%0; 0:"
|
||||
: "=r" (a)
|
||||
: "0" (a), "ir" (b)
|
||||
: "cc"
|
||||
);
|
||||
return(a);
|
||||
}
|
||||
|
||||
static __inline__ short GSM_SUB(short a, short b)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"subw %2,%0; jno 0f; movw $0x7fff,%0; adcw $0,%0; 0:"
|
||||
: "=r" (a)
|
||||
: "0" (a), "ir" (b)
|
||||
: "cc"
|
||||
);
|
||||
return(a);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
# define GSM_L_ADD(a, b) \
|
||||
( (a) < 0 ? ( (b) >= 0 ? (a) + (b) \
|
||||
: (utmp = (ulongword)-((a) + 1) + (ulongword)-((b) + 1)) \
|
||||
@@ -159,8 +121,6 @@ static __inline__ short GSM_SUB(short a, short b)
|
||||
((ltmp = (longword)(a) - (longword)(b)) >= MAX_WORD \
|
||||
? MAX_WORD : ltmp <= MIN_WORD ? MIN_WORD : ltmp)
|
||||
|
||||
#endif
|
||||
|
||||
# define GSM_ABS(a) ((a) < 0 ? ((a) == MIN_WORD ? MAX_WORD : -(a)) : (a))
|
||||
|
||||
/* Use these if necessary:
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
/* k6opt.h vector functions optimized for MMX extensions to x86
|
||||
*
|
||||
* Copyright (C) 1999 by Stanley J. Brooks <stabro@megsinet.net>
|
||||
*
|
||||
* Any use of this software is permitted provided that this notice is not
|
||||
* removed and that neither the authors nor the Technische Universitaet Berlin
|
||||
* are deemed to have made any representations as to the suitability of this
|
||||
* software for any purpose nor are held responsible for any defects of
|
||||
* this software. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE;
|
||||
* not even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE.
|
||||
*
|
||||
* Chicago, 03.12.1999
|
||||
* Stanley J. Brooks
|
||||
*/
|
||||
|
||||
extern void Weighting_filter P2((e, x),
|
||||
const word * e, /* signal [-5..0.39.44] IN */
|
||||
word * x /* signal [0..39] OUT */
|
||||
)
|
||||
;
|
||||
|
||||
extern longword k6maxcc P3((wt,dp,Nc_out),
|
||||
const word *wt,
|
||||
const word *dp,
|
||||
word * Nc_out /* OUT */
|
||||
)
|
||||
;
|
||||
/*
|
||||
* k6maxmin(p,n,out[])
|
||||
* input p[n] is array of shorts (require n>0)
|
||||
* returns (long) maximum absolute value..
|
||||
* if out!=NULL, also returns out[0] the maximum and out[1] the minimum
|
||||
*/
|
||||
extern longword k6maxmin P3((p,n,out),
|
||||
const word *p,
|
||||
int n,
|
||||
word *out /* out[0] is max, out[1] is min */
|
||||
)
|
||||
;
|
||||
|
||||
extern longword k6iprod P3((p,q,n),
|
||||
const word *p,
|
||||
const word *q,
|
||||
int n
|
||||
)
|
||||
;
|
||||
|
||||
/*
|
||||
* k6vsraw(p,n,bits)
|
||||
* input p[n] is array of shorts (require n>0)
|
||||
* shift/round each to the right by bits>=0 bits.
|
||||
*/
|
||||
extern void k6vsraw P3((p,n,bits),
|
||||
const word *p,
|
||||
int n,
|
||||
int bits
|
||||
)
|
||||
;
|
||||
|
||||
/*
|
||||
* k6vsllw(p,n,bits)
|
||||
* input p[n] is array of shorts (require n>0)
|
||||
* shift each to the left by bits>=0 bits.
|
||||
*/
|
||||
extern void k6vsllw P3((p,n,bits),
|
||||
const word *p,
|
||||
int n,
|
||||
int bits
|
||||
)
|
||||
;
|
||||
|
||||
#if 1 /* there isn't any significant speed gain from mmx here: */
|
||||
extern void Short_term_analysis_filteringx P4((u0,rp0,k_n,s),
|
||||
register word * u0,
|
||||
register word * rp0, /* [0..7] IN */
|
||||
register int k_n, /* k_end - k_start */
|
||||
register word * s /* [0..n-1] IN/OUT */
|
||||
)
|
||||
;
|
||||
/*
|
||||
#define Short_term_analysis_filtering Short_term_analysis_filteringx
|
||||
*/
|
||||
#endif
|
||||
@@ -1,739 +0,0 @@
|
||||
.file "k6opt.s"
|
||||
.version "01.01"
|
||||
/* gcc2_compiled.: */
|
||||
.section .rodata
|
||||
.align 4
|
||||
.type coefs,@object
|
||||
.size coefs,24
|
||||
coefs:
|
||||
.value -134
|
||||
.value -374
|
||||
.value 0
|
||||
.value 2054
|
||||
.value 5741
|
||||
.value 8192
|
||||
.value 5741
|
||||
.value 2054
|
||||
.value 0
|
||||
.value -374
|
||||
.value -134
|
||||
.value 0
|
||||
.text
|
||||
.align 4
|
||||
/* void Weighting_filter (const short *e, short *x) */
|
||||
.globl Weighting_filter
|
||||
.type Weighting_filter,@function
|
||||
Weighting_filter:
|
||||
pushl %ebp
|
||||
movl %esp,%ebp
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
pushl %ebx
|
||||
movl 12(%ebp),%edi
|
||||
movl 8(%ebp),%ebx
|
||||
addl $-10,%ebx
|
||||
emms
|
||||
movl $0x1000,%eax; movd %eax,%mm5 /* for rounding */
|
||||
movq coefs,%mm1
|
||||
movq coefs+8,%mm2
|
||||
movq coefs+16,%mm3
|
||||
xorl %esi,%esi
|
||||
.p2align 2
|
||||
.L21:
|
||||
movq (%ebx,%esi,2),%mm0
|
||||
pmaddwd %mm1,%mm0
|
||||
|
||||
movq 8(%ebx,%esi,2),%mm4
|
||||
pmaddwd %mm2,%mm4
|
||||
paddd %mm4,%mm0
|
||||
|
||||
movq 16(%ebx,%esi,2),%mm4
|
||||
pmaddwd %mm3,%mm4
|
||||
paddd %mm4,%mm0
|
||||
|
||||
movq %mm0,%mm4
|
||||
punpckhdq %mm0,%mm4 /* mm4 has high int32 of mm0 dup'd */
|
||||
paddd %mm4,%mm0;
|
||||
|
||||
paddd %mm5,%mm0 /* add for roundoff */
|
||||
psrad $13,%mm0
|
||||
packssdw %mm0,%mm0
|
||||
movd %mm0,%eax /* ax has result */
|
||||
movw %ax,(%edi,%esi,2)
|
||||
incl %esi
|
||||
cmpl $39,%esi
|
||||
jle .L21
|
||||
emms
|
||||
popl %ebx
|
||||
popl %esi
|
||||
popl %edi
|
||||
leave
|
||||
ret
|
||||
.Lfe1:
|
||||
.size Weighting_filter,.Lfe1-Weighting_filter
|
||||
|
||||
.macro ccstep n
|
||||
.if \n
|
||||
movq \n(%edi),%mm1
|
||||
movq \n(%esi),%mm2
|
||||
.else
|
||||
movq (%edi),%mm1
|
||||
movq (%esi),%mm2
|
||||
.endif
|
||||
pmaddwd %mm2,%mm1
|
||||
paddd %mm1,%mm0
|
||||
.endm
|
||||
|
||||
.align 4
|
||||
/* long k6maxcc(const short *wt, const short *dp, short *Nc_out) */
|
||||
.globl k6maxcc
|
||||
.type k6maxcc,@function
|
||||
k6maxcc:
|
||||
pushl %ebp
|
||||
movl %esp,%ebp
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
pushl %ebx
|
||||
emms
|
||||
movl 8(%ebp),%edi
|
||||
movl 12(%ebp),%esi
|
||||
movl $0,%edx /* will be maximum inner-product */
|
||||
movl $40,%ebx
|
||||
movl %ebx,%ecx /* will be index of max inner-product */
|
||||
subl $80,%esi
|
||||
.p2align 2
|
||||
.L41:
|
||||
movq (%edi),%mm0
|
||||
movq (%esi),%mm2
|
||||
pmaddwd %mm2,%mm0
|
||||
ccstep 8
|
||||
ccstep 16
|
||||
ccstep 24
|
||||
ccstep 32
|
||||
ccstep 40
|
||||
ccstep 48
|
||||
ccstep 56
|
||||
ccstep 64
|
||||
ccstep 72
|
||||
|
||||
movq %mm0,%mm1
|
||||
punpckhdq %mm0,%mm1 /* mm1 has high int32 of mm0 dup'd */
|
||||
paddd %mm1,%mm0;
|
||||
movd %mm0,%eax /* eax has result */
|
||||
|
||||
cmpl %edx,%eax
|
||||
jle .L40
|
||||
movl %eax,%edx
|
||||
movl %ebx,%ecx
|
||||
.p2align 2
|
||||
.L40:
|
||||
subl $2,%esi
|
||||
incl %ebx
|
||||
cmpl $120,%ebx
|
||||
jle .L41
|
||||
movl 16(%ebp),%eax
|
||||
movw %cx,(%eax)
|
||||
movl %edx,%eax
|
||||
emms
|
||||
popl %ebx
|
||||
popl %esi
|
||||
popl %edi
|
||||
leave
|
||||
ret
|
||||
.Lfe2:
|
||||
.size k6maxcc,.Lfe2-k6maxcc
|
||||
|
||||
|
||||
.align 4
|
||||
/* long k6iprod (const short *p, const short *q, int n) */
|
||||
.globl k6iprod
|
||||
.type k6iprod,@function
|
||||
k6iprod:
|
||||
pushl %ebp
|
||||
movl %esp,%ebp
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
emms
|
||||
pxor %mm0,%mm0
|
||||
movl 8(%ebp),%esi
|
||||
movl 12(%ebp),%edi
|
||||
movl 16(%ebp),%eax
|
||||
leal -32(%esi,%eax,2),%edx /* edx = top - 32 */
|
||||
|
||||
cmpl %edx,%esi; ja .L202
|
||||
|
||||
.p2align 2
|
||||
.L201:
|
||||
ccstep 0
|
||||
ccstep 8
|
||||
ccstep 16
|
||||
ccstep 24
|
||||
|
||||
addl $32,%esi
|
||||
addl $32,%edi
|
||||
cmpl %edx,%esi; jbe .L201
|
||||
|
||||
.p2align 2
|
||||
.L202:
|
||||
addl $24,%edx /* now edx = top-8 */
|
||||
cmpl %edx,%esi; ja .L205
|
||||
|
||||
.p2align 2
|
||||
.L203:
|
||||
ccstep 0
|
||||
|
||||
addl $8,%esi
|
||||
addl $8,%edi
|
||||
cmpl %edx,%esi; jbe .L203
|
||||
|
||||
.p2align 2
|
||||
.L205:
|
||||
addl $4,%edx /* now edx = top-4 */
|
||||
cmpl %edx,%esi; ja .L207
|
||||
|
||||
movd (%edi),%mm1
|
||||
movd (%esi),%mm2
|
||||
pmaddwd %mm2,%mm1
|
||||
paddd %mm1,%mm0
|
||||
|
||||
addl $4,%esi
|
||||
addl $4,%edi
|
||||
|
||||
.p2align 2
|
||||
.L207:
|
||||
addl $2,%edx /* now edx = top-2 */
|
||||
cmpl %edx,%esi; ja .L209
|
||||
|
||||
movswl (%edi),%eax
|
||||
movd %eax,%mm1
|
||||
movswl (%esi),%eax
|
||||
movd %eax,%mm2
|
||||
pmaddwd %mm2,%mm1
|
||||
paddd %mm1,%mm0
|
||||
|
||||
.p2align 2
|
||||
.L209:
|
||||
movq %mm0,%mm1
|
||||
punpckhdq %mm0,%mm1 /* mm1 has high int32 of mm0 dup'd */
|
||||
paddd %mm1,%mm0;
|
||||
movd %mm0,%eax /* eax has result */
|
||||
|
||||
emms
|
||||
popl %esi
|
||||
popl %edi
|
||||
leave
|
||||
ret
|
||||
.Lfe3:
|
||||
.size k6iprod,.Lfe3-k6iprod
|
||||
|
||||
|
||||
.align 4
|
||||
/* void k6vsraw P3((short *p, int n, int bits) */
|
||||
.globl k6vsraw
|
||||
.type k6vsraw,@function
|
||||
k6vsraw:
|
||||
pushl %ebp
|
||||
movl %esp,%ebp
|
||||
pushl %esi
|
||||
movl 8(%ebp),%esi
|
||||
movl 16(%ebp),%ecx
|
||||
andl %ecx,%ecx; jle .L399
|
||||
movl 12(%ebp),%eax
|
||||
leal -16(%esi,%eax,2),%edx /* edx = top - 16 */
|
||||
emms
|
||||
movd %ecx,%mm3
|
||||
movq ones,%mm2
|
||||
psllw %mm3,%mm2; psrlw $1,%mm2
|
||||
cmpl %edx,%esi; ja .L306
|
||||
|
||||
.p2align 2
|
||||
.L302: /* 8 words per iteration */
|
||||
movq (%esi),%mm0
|
||||
movq 8(%esi),%mm1
|
||||
paddsw %mm2,%mm0
|
||||
psraw %mm3,%mm0;
|
||||
paddsw %mm2,%mm1
|
||||
psraw %mm3,%mm1;
|
||||
movq %mm0,(%esi)
|
||||
movq %mm1,8(%esi)
|
||||
addl $16,%esi
|
||||
cmpl %edx,%esi
|
||||
jbe .L302
|
||||
|
||||
.p2align 2
|
||||
.L306:
|
||||
addl $12,%edx /* now edx = top-4 */
|
||||
cmpl %edx,%esi; ja .L310
|
||||
|
||||
.p2align 2
|
||||
.L308: /* do up to 6 words, two at a time */
|
||||
movd (%esi),%mm0
|
||||
paddsw %mm2,%mm0
|
||||
psraw %mm3,%mm0;
|
||||
movd %mm0,(%esi)
|
||||
addl $4,%esi
|
||||
cmpl %edx,%esi
|
||||
jbe .L308
|
||||
|
||||
.p2align 2
|
||||
.L310:
|
||||
addl $2,%edx /* now edx = top-2 */
|
||||
cmpl %edx,%esi; ja .L315
|
||||
|
||||
movzwl (%esi),%eax
|
||||
movd %eax,%mm0
|
||||
paddsw %mm2,%mm0
|
||||
psraw %mm3,%mm0;
|
||||
movd %mm0,%eax
|
||||
movw %ax,(%esi)
|
||||
|
||||
.p2align 2
|
||||
.L315:
|
||||
emms
|
||||
.L399:
|
||||
popl %esi
|
||||
leave
|
||||
ret
|
||||
.Lfe4:
|
||||
.size k6vsraw,.Lfe4-k6vsraw
|
||||
|
||||
.align 4
|
||||
/* void k6vsllw P3((short *p, int n, int bits) */
|
||||
.globl k6vsllw
|
||||
.type k6vsllw,@function
|
||||
k6vsllw:
|
||||
pushl %ebp
|
||||
movl %esp,%ebp
|
||||
pushl %esi
|
||||
movl 8(%ebp),%esi
|
||||
movl 16(%ebp),%ecx
|
||||
andl %ecx,%ecx; jle .L499
|
||||
movl 12(%ebp),%eax
|
||||
leal -16(%esi,%eax,2),%edx /* edx = top - 16 */
|
||||
emms
|
||||
movd %ecx,%mm3
|
||||
cmpl %edx,%esi; ja .L406
|
||||
|
||||
.p2align 2
|
||||
.L402: /* 8 words per iteration */
|
||||
movq (%esi),%mm0
|
||||
movq 8(%esi),%mm1
|
||||
psllw %mm3,%mm0;
|
||||
psllw %mm3,%mm1;
|
||||
movq %mm0,(%esi)
|
||||
movq %mm1,8(%esi)
|
||||
addl $16,%esi
|
||||
cmpl %edx,%esi
|
||||
jbe .L402
|
||||
|
||||
.p2align 2
|
||||
.L406:
|
||||
addl $12,%edx /* now edx = top-4 */
|
||||
cmpl %edx,%esi; ja .L410
|
||||
|
||||
.p2align 2
|
||||
.L408: /* do up to 6 words, two at a time */
|
||||
movd (%esi),%mm0
|
||||
psllw %mm3,%mm0;
|
||||
movd %mm0,(%esi)
|
||||
addl $4,%esi
|
||||
cmpl %edx,%esi
|
||||
jbe .L408
|
||||
|
||||
.p2align 2
|
||||
.L410:
|
||||
addl $2,%edx /* now edx = top-2 */
|
||||
cmpl %edx,%esi; ja .L415
|
||||
|
||||
movzwl (%esi),%eax
|
||||
movd %eax,%mm0
|
||||
psllw %mm3,%mm0;
|
||||
movd %mm0,%eax
|
||||
movw %ax,(%esi)
|
||||
|
||||
.p2align 2
|
||||
.L415:
|
||||
emms
|
||||
.L499:
|
||||
popl %esi
|
||||
leave
|
||||
ret
|
||||
.Lfe5:
|
||||
.size k6vsllw,.Lfe5-k6vsllw
|
||||
|
||||
|
||||
.section .rodata
|
||||
.align 4
|
||||
.type extremes,@object
|
||||
.size extremes,8
|
||||
extremes:
|
||||
.long 0x80008000
|
||||
.long 0x7fff7fff
|
||||
.type ones,@object
|
||||
.size ones,8
|
||||
ones:
|
||||
.long 0x00010001
|
||||
.long 0x00010001
|
||||
|
||||
.text
|
||||
.align 4
|
||||
/* long k6maxmin (const short *p, int n, short *out) */
|
||||
.globl k6maxmin
|
||||
.type k6maxmin,@function
|
||||
k6maxmin:
|
||||
pushl %ebp
|
||||
movl %esp,%ebp
|
||||
pushl %esi
|
||||
emms
|
||||
movl 8(%ebp),%esi
|
||||
movl 12(%ebp),%eax
|
||||
leal -8(%esi,%eax,2),%edx
|
||||
|
||||
cmpl %edx,%esi
|
||||
jbe .L52
|
||||
movd extremes,%mm0
|
||||
movd extremes+4,%mm1
|
||||
jmp .L58
|
||||
|
||||
.p2align 2
|
||||
.L52:
|
||||
movq (%esi),%mm0 /* mm0 will be max's */
|
||||
movq %mm0,%mm1 /* mm1 will be min's */
|
||||
addl $8,%esi
|
||||
cmpl %edx,%esi
|
||||
ja .L56
|
||||
|
||||
.p2align 2
|
||||
.L54:
|
||||
movq (%esi),%mm2
|
||||
|
||||
movq %mm2,%mm3
|
||||
pcmpgtw %mm0,%mm3 /* mm3 is bitmask for words where mm2 > mm0 */
|
||||
movq %mm3,%mm4
|
||||
pand %mm2,%mm3 /* mm3 is mm2 masked to new max's */
|
||||
pandn %mm0,%mm4 /* mm4 is mm0 masked to its max's */
|
||||
por %mm3,%mm4
|
||||
movq %mm4,%mm0 /* now mm0 is updated max's */
|
||||
|
||||
movq %mm1,%mm3
|
||||
pcmpgtw %mm2,%mm3 /* mm3 is bitmask for words where mm2 < mm1 */
|
||||
pand %mm3,%mm2 /* mm2 is mm2 masked to new min's */
|
||||
pandn %mm1,%mm3 /* mm3 is mm1 masked to its min's */
|
||||
por %mm3,%mm2
|
||||
movq %mm2,%mm1 /* now mm1 is updated min's */
|
||||
|
||||
addl $8,%esi
|
||||
cmpl %edx,%esi
|
||||
jbe .L54
|
||||
|
||||
.p2align 2
|
||||
.L56: /* merge down the 4-word max/mins to lower 2 words */
|
||||
|
||||
movq %mm0,%mm2
|
||||
psrlq $32,%mm2
|
||||
movq %mm2,%mm3
|
||||
pcmpgtw %mm0,%mm3 /* mm3 is bitmask for words where mm2 > mm0 */
|
||||
pand %mm3,%mm2 /* mm2 is mm2 masked to new max's */
|
||||
pandn %mm0,%mm3 /* mm3 is mm0 masked to its max's */
|
||||
por %mm3,%mm2
|
||||
movq %mm2,%mm0 /* now mm0 is updated max's */
|
||||
|
||||
movq %mm1,%mm2
|
||||
psrlq $32,%mm2
|
||||
movq %mm1,%mm3
|
||||
pcmpgtw %mm2,%mm3 /* mm3 is bitmask for words where mm2 < mm1 */
|
||||
pand %mm3,%mm2 /* mm2 is mm2 masked to new min's */
|
||||
pandn %mm1,%mm3 /* mm3 is mm1 masked to its min's */
|
||||
por %mm3,%mm2
|
||||
movq %mm2,%mm1 /* now mm1 is updated min's */
|
||||
|
||||
.p2align 2
|
||||
.L58:
|
||||
addl $4,%edx /* now dx = top-4 */
|
||||
cmpl %edx,%esi
|
||||
ja .L62
|
||||
/* here, there are >= 2 words of input remaining */
|
||||
movd (%esi),%mm2
|
||||
|
||||
movq %mm2,%mm3
|
||||
pcmpgtw %mm0,%mm3 /* mm3 is bitmask for words where mm2 > mm0 */
|
||||
movq %mm3,%mm4
|
||||
pand %mm2,%mm3 /* mm3 is mm2 masked to new max's */
|
||||
pandn %mm0,%mm4 /* mm4 is mm0 masked to its max's */
|
||||
por %mm3,%mm4
|
||||
movq %mm4,%mm0 /* now mm0 is updated max's */
|
||||
|
||||
movq %mm1,%mm3
|
||||
pcmpgtw %mm2,%mm3 /* mm3 is bitmask for words where mm2 < mm1 */
|
||||
pand %mm3,%mm2 /* mm2 is mm2 masked to new min's */
|
||||
pandn %mm1,%mm3 /* mm3 is mm1 masked to its min's */
|
||||
por %mm3,%mm2
|
||||
movq %mm2,%mm1 /* now mm1 is updated min's */
|
||||
|
||||
addl $4,%esi
|
||||
|
||||
.p2align 2
|
||||
.L62:
|
||||
/* merge down the 2-word max/mins to 1 word */
|
||||
|
||||
movq %mm0,%mm2
|
||||
psrlq $16,%mm2
|
||||
movq %mm2,%mm3
|
||||
pcmpgtw %mm0,%mm3 /* mm3 is bitmask for words where mm2 > mm0 */
|
||||
pand %mm3,%mm2 /* mm2 is mm2 masked to new max's */
|
||||
pandn %mm0,%mm3 /* mm3 is mm0 masked to its max's */
|
||||
por %mm3,%mm2
|
||||
movd %mm2,%ecx /* cx is max so far */
|
||||
|
||||
movq %mm1,%mm2
|
||||
psrlq $16,%mm2
|
||||
movq %mm1,%mm3
|
||||
pcmpgtw %mm2,%mm3 /* mm3 is bitmask for words where mm2 < mm1 */
|
||||
pand %mm3,%mm2 /* mm2 is mm2 masked to new min's */
|
||||
pandn %mm1,%mm3 /* mm3 is mm1 masked to its min's */
|
||||
por %mm3,%mm2
|
||||
movd %mm2,%eax /* ax is min so far */
|
||||
|
||||
addl $2,%edx /* now dx = top-2 */
|
||||
cmpl %edx,%esi
|
||||
ja .L65
|
||||
|
||||
/* here, there is one word of input left */
|
||||
cmpw (%esi),%cx
|
||||
jge .L64
|
||||
movw (%esi),%cx
|
||||
.p2align 2
|
||||
.L64:
|
||||
cmpw (%esi),%ax
|
||||
jle .L65
|
||||
movw (%esi),%ax
|
||||
|
||||
.p2align 2
|
||||
.L65: /* (finally!) cx is the max, ax the min */
|
||||
movswl %cx,%ecx
|
||||
movswl %ax,%eax
|
||||
|
||||
movl 16(%ebp),%edx /* ptr to output max,min vals */
|
||||
andl %edx,%edx; jz .L77
|
||||
movw %cx,(%edx) /* max */
|
||||
movw %ax,2(%edx) /* min */
|
||||
.p2align 2
|
||||
.L77:
|
||||
/* now calculate max absolute val */
|
||||
negl %eax
|
||||
cmpl %ecx,%eax
|
||||
jge .L81
|
||||
movl %ecx,%eax
|
||||
.p2align 2
|
||||
.L81:
|
||||
emms
|
||||
popl %esi
|
||||
leave
|
||||
ret
|
||||
.Lfe6:
|
||||
.size k6maxmin,.Lfe6-k6maxmin
|
||||
|
||||
/* void Short_term_analysis_filtering (short *u0, const short *rp0, int kn, short *s) */
|
||||
.equiv pm_u0,8
|
||||
.equiv pm_rp0,12
|
||||
.equiv pm_kn,16
|
||||
.equiv pm_s,20
|
||||
.equiv lv_u_top,-4
|
||||
.equiv lv_s_top,-8
|
||||
.equiv lv_rp,-40 /* local version of rp0 with each word twice */
|
||||
.align 4
|
||||
.globl Short_term_analysis_filteringx
|
||||
.type Short_term_analysis_filteringx,@function
|
||||
Short_term_analysis_filteringx:
|
||||
pushl %ebp
|
||||
movl %esp,%ebp
|
||||
subl $40,%esp
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
|
||||
movl pm_rp0(%ebp),%esi;
|
||||
leal lv_rp(%ebp),%edi;
|
||||
cld
|
||||
lodsw; stosw; stosw
|
||||
lodsw; stosw; stosw
|
||||
lodsw; stosw; stosw
|
||||
lodsw; stosw; stosw
|
||||
lodsw; stosw; stosw
|
||||
lodsw; stosw; stosw
|
||||
lodsw; stosw; stosw
|
||||
lodsw; stosw; stosw
|
||||
emms
|
||||
movl $0x4000,%eax;
|
||||
movd %eax,%mm4;
|
||||
punpckldq %mm4,%mm4 /* (0x00004000,0x00004000) for rounding dword product pairs */
|
||||
|
||||
movl pm_u0(%ebp),%eax
|
||||
addl $16,%eax
|
||||
movl %eax,lv_u_top(%ebp) /* UTOP */
|
||||
movl pm_s(%ebp),%edx /* edx is local s ptr throughout below */
|
||||
movl pm_kn(%ebp),%eax
|
||||
leal (%edx,%eax,2),%eax
|
||||
movl %eax,lv_s_top(%ebp)
|
||||
cmpl %eax,%edx
|
||||
jae .L179
|
||||
.p2align 2
|
||||
.L181:
|
||||
leal lv_rp(%ebp),%esi /* RP */
|
||||
movl pm_u0(%ebp),%edi /* U */
|
||||
movw (%edx),%ax /* (0,DI) */
|
||||
roll $16,%eax
|
||||
movw (%edx),%ax /* (DI,DI) */
|
||||
.p2align 2
|
||||
.L185: /* RP is %esi */
|
||||
movl %eax,%ecx
|
||||
movw (%edi),%ax /* (DI,U) */
|
||||
movd (%esi),%mm3 /* mm3 is (0,0,RP,RP) */
|
||||
movw %cx,(%edi)
|
||||
|
||||
movd %eax,%mm2 /* mm2 is (0,0,DI,U) */
|
||||
rorl $16,%eax
|
||||
movd %eax,%mm1 /* mm1 is (0,0,U,DI) */
|
||||
|
||||
movq %mm1,%mm0
|
||||
pmullw %mm3,%mm0
|
||||
pmulhw %mm3,%mm1
|
||||
punpcklwd %mm1,%mm0 /* mm0 is (RP*U,RP*DI) */
|
||||
paddd %mm4,%mm0 /* mm4 is 0x00004000,0x00004000 */
|
||||
psrad $15,%mm0 /* (RP*U,RP*DI) adjusted */
|
||||
packssdw %mm0,%mm0 /* (*,*,RP*U,RP*DI) adjusted and saturated to word */
|
||||
paddsw %mm2,%mm0 /* mm0 is (?,?, DI', U') */
|
||||
movd %mm0,%eax /* (DI,U') */
|
||||
|
||||
addl $2,%edi
|
||||
addl $4,%esi
|
||||
cmpl lv_u_top(%ebp),%edi
|
||||
jb .L185
|
||||
|
||||
rorl $16,%eax
|
||||
movw %ax,(%edx) /* last DI goes to *s */
|
||||
addl $2,%edx /* next s */
|
||||
cmpl lv_s_top(%ebp),%edx
|
||||
jb .L181
|
||||
.p2align 2
|
||||
.L179:
|
||||
emms
|
||||
popl %esi
|
||||
popl %edi
|
||||
leave
|
||||
ret
|
||||
.Lfe7:
|
||||
.size Short_term_analysis_filteringx,.Lfe7-Short_term_analysis_filteringx
|
||||
|
||||
.end
|
||||
|
||||
/* 'as' macro's seem to be case-insensitive */
|
||||
.macro STEP n
|
||||
.if \n
|
||||
movd \n(%esi),%mm3 /* mm3 is (0,0,RP,RP) */
|
||||
.else
|
||||
movd (%esi),%mm3 /* mm3 is (0,0,RP,RP) */
|
||||
.endif
|
||||
movq %mm5,%mm1;
|
||||
movd %mm4,%ecx; movw %cx,%ax /* (DI,U) */
|
||||
psllq $48,%mm1; psrlq $16,%mm4; por %mm1,%mm4
|
||||
psllq $48,%mm0; psrlq $16,%mm5; por %mm0,%mm5
|
||||
|
||||
movd %eax,%mm2 /* mm2 is (0,0,DI,U) */
|
||||
rorl $16,%eax
|
||||
movd %eax,%mm1 /* mm1 is (0,0,U,DI) */
|
||||
|
||||
movq %mm1,%mm0
|
||||
pmullw %mm3,%mm0
|
||||
pmulhw %mm3,%mm1
|
||||
punpcklwd %mm1,%mm0 /* mm0 is (RP*U,RP*DI) */
|
||||
paddd %mm6,%mm0 /* mm6 is 0x00004000,0x00004000 */
|
||||
psrad $15,%mm0 /* (RP*U,RP*DI) adjusted */
|
||||
packssdw %mm0,%mm0 /* (*,*,RP*U,RP*DI) adjusted and saturated to word */
|
||||
paddsw %mm2,%mm0 /* mm0 is (?,?, DI', U') */
|
||||
movd %mm0,%eax /* (DI,U') */
|
||||
.endm
|
||||
|
||||
/* void Short_term_analysis_filtering (short *u0, const short *rp0, int kn, short *s) */
|
||||
.equiv pm_u0,8
|
||||
.equiv pm_rp0,12
|
||||
.equiv pm_kn,16
|
||||
.equiv pm_s,20
|
||||
.equiv lv_rp_top,-4
|
||||
.equiv lv_s_top,-8
|
||||
.equiv lv_rp,-40 /* local version of rp0 with each word twice */
|
||||
.align 4
|
||||
.globl Short_term_analysis_filteringx
|
||||
.type Short_term_analysis_filteringx,@function
|
||||
Short_term_analysis_filteringx:
|
||||
pushl %ebp
|
||||
movl %esp,%ebp
|
||||
subl $56,%esp
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
pushl %ebx
|
||||
|
||||
movl pm_rp0(%ebp),%esi;
|
||||
leal lv_rp(%ebp),%edi;
|
||||
cld
|
||||
lodsw; stosw; stosw
|
||||
lodsw; stosw; stosw
|
||||
lodsw; stosw; stosw
|
||||
lodsw; stosw; stosw
|
||||
lodsw; stosw; stosw
|
||||
lodsw; stosw; stosw
|
||||
lodsw; stosw; stosw
|
||||
lodsw; stosw; stosw
|
||||
movl %edi,lv_rp_top(%ebp)
|
||||
emms
|
||||
|
||||
movl $0x4000,%eax;
|
||||
movd %eax,%mm6;
|
||||
punpckldq %mm6,%mm6 /* (0x00004000,0x00004000) for rounding dword product pairs */
|
||||
|
||||
movl pm_u0(%ebp),%ebx
|
||||
movq (%ebx),%mm4; movq 8(%ebx),%mm5 /* the 8 u's */
|
||||
movl pm_s(%ebp),%edx /* edx is local s ptr throughout below */
|
||||
movl pm_kn(%ebp),%eax
|
||||
leal (%edx,%eax,2),%eax
|
||||
movl %eax,lv_s_top(%ebp)
|
||||
cmpl %eax,%edx
|
||||
jae .L179
|
||||
.p2align 2
|
||||
.L181:
|
||||
leal lv_rp(%ebp),%esi /* RP */
|
||||
movw (%edx),%ax /* (0,DI) */
|
||||
roll $16,%eax
|
||||
movw (%edx),%ax /* (DI,DI) */
|
||||
movd %eax,%mm0
|
||||
.p2align 2
|
||||
.L185: /* RP is %esi */
|
||||
step 0
|
||||
step 4
|
||||
step 8
|
||||
step 12
|
||||
/*
|
||||
step 16
|
||||
step 20
|
||||
step 24
|
||||
step 28
|
||||
*/
|
||||
addl $16,%esi
|
||||
cmpl lv_rp_top(%ebp),%esi
|
||||
jb .L185
|
||||
|
||||
rorl $16,%eax
|
||||
movw %ax,(%edx) /* last DI goes to *s */
|
||||
addl $2,%edx /* next s */
|
||||
cmpl lv_s_top(%ebp),%edx
|
||||
jb .L181
|
||||
.L179:
|
||||
movq %mm4,(%ebx); movq %mm5,8(%ebx) /* the 8 u's */
|
||||
emms
|
||||
popl %ebx
|
||||
popl %esi
|
||||
popl %edi
|
||||
leave
|
||||
ret
|
||||
.Lfe7:
|
||||
.size Short_term_analysis_filteringx,.Lfe7-Short_term_analysis_filteringx
|
||||
.ident "GCC: (GNU) 2.95.2 19991109 (Debian GNU/Linux)"
|
||||
@@ -13,9 +13,7 @@
|
||||
|
||||
#include "gsm.h"
|
||||
#include "proto.h"
|
||||
#ifdef K6OPT
|
||||
#include "k6opt.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 4.2.11 .. 4.2.12 LONG TERM PREDICTOR (LTP) SECTION
|
||||
*/
|
||||
@@ -199,9 +197,6 @@ static void Calculation_of_the_LTP_parameters P4((d,dp,bc_out,Nc_out),
|
||||
|
||||
/* Search for the maximum cross-correlation and coding of the LTP lag
|
||||
*/
|
||||
# ifdef K6OPT
|
||||
L_max = k6maxcc(wt,dp,&Nc);
|
||||
# else
|
||||
L_max = 0;
|
||||
Nc = 40; /* index for the maximum cross-correlation */
|
||||
|
||||
@@ -239,7 +234,7 @@ static void Calculation_of_the_LTP_parameters P4((d,dp,bc_out,Nc_out),
|
||||
L_max = L_result;
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
*Nc_out = Nc;
|
||||
|
||||
L_max <<= 1;
|
||||
|
||||
@@ -14,10 +14,6 @@
|
||||
#include "gsm.h"
|
||||
#include "proto.h"
|
||||
|
||||
#ifdef K6OPT
|
||||
#include "k6opt.h"
|
||||
#endif
|
||||
|
||||
#undef P
|
||||
|
||||
/*
|
||||
@@ -48,19 +44,12 @@ static void Autocorrelation P2((s, L_ACF),
|
||||
|
||||
/* Search for the maximum.
|
||||
*/
|
||||
#ifndef K6OPT
|
||||
smax = 0;
|
||||
for (k = 0; k <= 159; k++) {
|
||||
temp = GSM_ABS( s[k] );
|
||||
if (temp > smax) smax = temp;
|
||||
}
|
||||
#else
|
||||
{
|
||||
longword lmax;
|
||||
lmax = k6maxmin(s,160,NULL);
|
||||
smax = (lmax > MAX_WORD) ? MAX_WORD : lmax;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Computation of the scaling factor.
|
||||
*/
|
||||
if (smax == 0) scalauto = 0;
|
||||
@@ -73,7 +62,6 @@ static void Autocorrelation P2((s, L_ACF),
|
||||
*/
|
||||
|
||||
if (scalauto > 0) {
|
||||
# ifndef K6OPT
|
||||
|
||||
# ifdef USE_FLOAT_MUL
|
||||
# define SCALE(n) \
|
||||
@@ -95,10 +83,6 @@ static void Autocorrelation P2((s, L_ACF),
|
||||
SCALE(4)
|
||||
}
|
||||
# undef SCALE
|
||||
|
||||
# else /* K6OPT */
|
||||
k6vsraw(s,160,scalauto);
|
||||
# endif
|
||||
}
|
||||
# ifdef USE_FLOAT_MUL
|
||||
else for (k = 0; k <= 159; k++) float_s[k] = (float) s[k];
|
||||
@@ -106,7 +90,6 @@ static void Autocorrelation P2((s, L_ACF),
|
||||
|
||||
/* Compute the L_ACF[..].
|
||||
*/
|
||||
#ifndef K6OPT
|
||||
{
|
||||
# ifdef USE_FLOAT_MUL
|
||||
register float * sp = float_s;
|
||||
@@ -153,24 +136,11 @@ static void Autocorrelation P2((s, L_ACF),
|
||||
for (k = 9; k--; L_ACF[k] <<= 1) ;
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
{
|
||||
int k;
|
||||
for (k=0; k<9; k++) {
|
||||
L_ACF[k] = 2*k6iprod(s,s+k,160-k);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* Rescaling of the array s[0..159]
|
||||
*/
|
||||
if (scalauto > 0) {
|
||||
assert(scalauto <= 4);
|
||||
#ifndef K6OPT
|
||||
for (k = 160; k--; *s++ <<= scalauto) ;
|
||||
# else /* K6OPT */
|
||||
k6vsllw(s,160,scalauto);
|
||||
# endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,8 +42,11 @@ void Gsm_Preprocess P3((S, s, so),
|
||||
word mp = S->mp;
|
||||
|
||||
word s1;
|
||||
longword L_s2;
|
||||
|
||||
longword L_temp;
|
||||
|
||||
word msp, lsp;
|
||||
word SO;
|
||||
|
||||
longword ltmp; /* for ADD */
|
||||
@@ -55,8 +58,7 @@ void Gsm_Preprocess P3((S, s, so),
|
||||
|
||||
/* 4.2.1 Downscaling of the input signal
|
||||
*/
|
||||
/* SO = SASR( *s, 3 ) << 2;*/
|
||||
SO = SASR( *s, 1 ) & ~3;
|
||||
SO = SASR( *s, 3 ) << 2;
|
||||
s++;
|
||||
|
||||
assert (SO >= -0x4000); /* downscaled by */
|
||||
@@ -78,38 +80,21 @@ void Gsm_Preprocess P3((S, s, so),
|
||||
|
||||
assert(s1 != MIN_WORD);
|
||||
|
||||
/* SJB Remark: float might be faster than the mess that follows */
|
||||
|
||||
/* Compute the recursive part
|
||||
*/
|
||||
L_s2 = s1;
|
||||
L_s2 <<= 15;
|
||||
|
||||
/* Execution of a 31 bv 16 bits multiplication
|
||||
*/
|
||||
{
|
||||
word msp, lsp;
|
||||
longword L_s2;
|
||||
longword L_temp;
|
||||
|
||||
L_s2 = s1;
|
||||
L_s2 <<= 15;
|
||||
#ifndef __GNUC__
|
||||
|
||||
msp = SASR( L_z2, 15 );
|
||||
lsp = L_z2 & 0x7fff; /* gsm_L_sub(L_z2,(msp<<15)); */
|
||||
lsp = L_z2-((longword)msp<<15); /* gsm_L_sub(L_z2,(msp<<15)); */
|
||||
|
||||
L_s2 += GSM_MULT_R( lsp, 32735 );
|
||||
L_temp = (longword)msp * 32735; /* GSM_L_MULT(msp,32735) >> 1;*/
|
||||
L_z2 = GSM_L_ADD( L_temp, L_s2 );
|
||||
/* above does L_z2 = L_z2 * 0x7fd5/0x8000 + L_s2 */
|
||||
#else
|
||||
L_z2 = ((long long)L_z2*32735 + 0x4000)>>15;
|
||||
/* alternate (ansi) version of above line does slightly different rounding:
|
||||
* L_temp = L_z2 >> 9;
|
||||
* L_temp += L_temp >> 5;
|
||||
* L_temp = (++L_temp) >> 1;
|
||||
* L_z2 = L_z2 - L_temp;
|
||||
*/
|
||||
L_z2 = GSM_L_ADD(L_z2,L_s2);
|
||||
#endif
|
||||
|
||||
/* Compute sof[k] with rounding
|
||||
*/
|
||||
L_temp = GSM_L_ADD( L_z2, 16384 );
|
||||
@@ -120,7 +105,6 @@ void Gsm_Preprocess P3((S, s, so),
|
||||
msp = GSM_MULT_R( mp, -28180 );
|
||||
mp = SASR( L_temp, 15 );
|
||||
*so++ = GSM_ADD( mp, msp );
|
||||
}
|
||||
}
|
||||
|
||||
S->z1 = z1;
|
||||
|
||||
@@ -18,9 +18,7 @@
|
||||
*/
|
||||
|
||||
/* 4.2.13 */
|
||||
#ifdef K6OPT
|
||||
#include "k6opt.h"
|
||||
#else
|
||||
|
||||
static void Weighting_filter P2((e, x),
|
||||
register word * e, /* signal [-5..0.39.44] IN */
|
||||
word * x /* signal [0..39] OUT */
|
||||
@@ -112,7 +110,6 @@ static void Weighting_filter P2((e, x),
|
||||
: (L_result > MAX_WORD ? MAX_WORD : L_result ));
|
||||
}
|
||||
}
|
||||
#endif /* K6OPT */
|
||||
|
||||
/* 4.2.14 */
|
||||
|
||||
|
||||
@@ -13,12 +13,7 @@
|
||||
|
||||
#include "gsm.h"
|
||||
#include "proto.h"
|
||||
#ifdef K6OPT
|
||||
#include "k6opt.h"
|
||||
|
||||
#define Short_term_analysis_filtering Short_term_analysis_filteringx
|
||||
|
||||
#endif
|
||||
/*
|
||||
* SHORT TERM ANALYSIS FILTERING SECTION
|
||||
*/
|
||||
@@ -185,16 +180,9 @@ static void LARp_to_rp P1((LARp),
|
||||
|
||||
|
||||
/* 4.2.10 */
|
||||
#ifndef Short_term_analysis_filtering
|
||||
|
||||
/* SJB Remark:
|
||||
* I tried 2 MMX versions of this function, neither is significantly
|
||||
* faster than the C version which follows. MMX might be useful if
|
||||
* one were processing 2 input streams in parallel.
|
||||
*/
|
||||
static void Short_term_analysis_filtering P4((u0,rp0,k_n,s),
|
||||
register word * u0,
|
||||
register word * rp0, /* [0..7] IN */
|
||||
static void Short_term_analysis_filtering P4((S,rp,k_n,s),
|
||||
struct gsm_state * S,
|
||||
register word * rp, /* [0..7] IN */
|
||||
register int k_n, /* k_end - k_start */
|
||||
register word * s /* [0..n-1] IN/OUT */
|
||||
)
|
||||
@@ -206,45 +194,45 @@ static void Short_term_analysis_filtering P4((u0,rp0,k_n,s),
|
||||
* coefficient), it is assumed that the computation begins with index
|
||||
* k_start (for arrays d[..] and s[..]) and stops with index k_end
|
||||
* (k_start and k_end are defined in 4.2.9.1). This procedure also
|
||||
* needs to keep the array u0[0..7] in memory for each call.
|
||||
* needs to keep the array u[0..7] in memory for each call.
|
||||
*/
|
||||
{
|
||||
register word * u_top = u0 + 8;
|
||||
register word * s_top = s + k_n;
|
||||
register word * u = S->u;
|
||||
register int i;
|
||||
register word di, zzz, ui, sav, rpi;
|
||||
register longword ltmp;
|
||||
|
||||
while (s < s_top) {
|
||||
register word *u, *rp ;
|
||||
register longword di, u_out;
|
||||
di = u_out = *s;
|
||||
for (rp=rp0, u=u0; u<u_top;) {
|
||||
register longword ui, rpi;
|
||||
ui = *u;
|
||||
*u++ = u_out;
|
||||
rpi = *rp++;
|
||||
u_out = ui + (((rpi*di)+0x4000)>>15);
|
||||
di = di + (((rpi*ui)+0x4000)>>15);
|
||||
/* make the common case fastest: */
|
||||
if ((u_out == (word)u_out) && (di == (word)di)) continue;
|
||||
/* otherwise do slower fixup (saturation) */
|
||||
if (u_out>MAX_WORD) u_out=MAX_WORD;
|
||||
else if (u_out<MIN_WORD) u_out=MIN_WORD;
|
||||
if (di>MAX_WORD) di=MAX_WORD;
|
||||
else if (di<MIN_WORD) di=MIN_WORD;
|
||||
for (; k_n--; s++) {
|
||||
|
||||
di = sav = *s;
|
||||
|
||||
for (i = 0; i < 8; i++) { /* YYY */
|
||||
|
||||
ui = u[i];
|
||||
rpi = rp[i];
|
||||
u[i] = sav;
|
||||
|
||||
zzz = GSM_MULT_R(rpi, di);
|
||||
sav = GSM_ADD( ui, zzz);
|
||||
|
||||
zzz = GSM_MULT_R(rpi, ui);
|
||||
di = GSM_ADD( di, zzz );
|
||||
}
|
||||
*s++ = di;
|
||||
|
||||
*s = di;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(USE_FLOAT_MUL) && defined(FAST)
|
||||
|
||||
static void Fast_Short_term_analysis_filtering P4((u,rp,k_n,s),
|
||||
register word * u;
|
||||
static void Fast_Short_term_analysis_filtering P4((S,rp,k_n,s),
|
||||
struct gsm_state * S,
|
||||
register word * rp, /* [0..7] IN */
|
||||
register int k_n, /* k_end - k_start */
|
||||
register word * s /* [0..n-1] IN/OUT */
|
||||
)
|
||||
{
|
||||
register word * u = S->u;
|
||||
register int i;
|
||||
|
||||
float uf[8],
|
||||
@@ -274,15 +262,6 @@ static void Fast_Short_term_analysis_filtering P4((u,rp,k_n,s),
|
||||
}
|
||||
#endif /* ! (defined (USE_FLOAT_MUL) && defined (FAST)) */
|
||||
|
||||
/*
|
||||
* SJB Remark: modified Short_term_synthesis_filtering() below
|
||||
* for significant (abt 35%) speedup of decompression.
|
||||
* (gcc-2.95, k6 cpu)
|
||||
* Please don't change this without benchmarking decompression
|
||||
* to see that you haven't harmed speed.
|
||||
* This function burns most of CPU time for untoasting.
|
||||
* Unfortunately, didn't see any good way to benefit from mmx.
|
||||
*/
|
||||
static void Short_term_synthesis_filtering P5((S,rrp,k,wt,sr),
|
||||
struct gsm_state * S,
|
||||
register word * rrp, /* [0..7] IN */
|
||||
@@ -293,34 +272,32 @@ static void Short_term_synthesis_filtering P5((S,rrp,k,wt,sr),
|
||||
{
|
||||
register word * v = S->v;
|
||||
register int i;
|
||||
register longword sri;
|
||||
register word sri, tmp1, tmp2;
|
||||
register longword ltmp; /* for GSM_ADD & GSM_SUB */
|
||||
|
||||
while (k--) {
|
||||
sri = *wt++;
|
||||
for (i = 8; i--;) {
|
||||
register longword tmp1, tmp2;
|
||||
|
||||
/* sri = GSM_SUB( sri, gsm_mult_r( rrp[i], v[i] ) );
|
||||
*/
|
||||
tmp1 = rrp[i];
|
||||
tmp2 = v[i];
|
||||
tmp2 = ( tmp1 == MIN_WORD && tmp2 == MIN_WORD
|
||||
? MAX_WORD
|
||||
: 0x0FFFF & (( (longword)tmp1 * (longword)tmp2
|
||||
+ 16384) >> 15)) ;
|
||||
|
||||
sri = GSM_SUB( sri, tmp2 );
|
||||
|
||||
tmp2 = (( tmp1 * tmp2 + 16384) >> 15) ;
|
||||
/* saturation done below */
|
||||
sri -= tmp2;
|
||||
if (sri != (word)sri) {
|
||||
sri = (sri<0)? MIN_WORD:MAX_WORD;
|
||||
}
|
||||
/* v[i+1] = GSM_ADD( v[i], gsm_mult_r( rrp[i], sri ) );
|
||||
*/
|
||||
tmp1 = ( tmp1 == MIN_WORD && sri == MIN_WORD
|
||||
? MAX_WORD
|
||||
: 0x0FFFF & (( (longword)tmp1 * (longword)sri
|
||||
+ 16384) >> 15)) ;
|
||||
|
||||
tmp1 = (( tmp1 * sri + 16384) >> 15) ;
|
||||
/* saturation done below */
|
||||
tmp1 += v[i];
|
||||
if (tmp1 != (word)tmp1) {
|
||||
tmp1 = (tmp1<0)? MIN_WORD:MAX_WORD;
|
||||
}
|
||||
v[i+1] = tmp1;
|
||||
v[i+1] = GSM_ADD( v[i], tmp1);
|
||||
}
|
||||
*sr++ = v[0] = sri;
|
||||
}
|
||||
@@ -378,7 +355,7 @@ void Gsm_Short_Term_Analysis_Filter P3((S,LARc,s),
|
||||
word * LARpp_j_1 = S->LARpp[ S->j ^= 1 ];
|
||||
|
||||
word LARp[8];
|
||||
int i;
|
||||
|
||||
#undef FILTER
|
||||
#if defined(FAST) && defined(USE_FLOAT_MUL)
|
||||
# define FILTER (* (S->fast \
|
||||
@@ -393,20 +370,19 @@ int i;
|
||||
|
||||
Coefficients_0_12( LARpp_j_1, LARpp_j, LARp );
|
||||
LARp_to_rp( LARp );
|
||||
FILTER( S->u, LARp, 13, s);
|
||||
FILTER( S, LARp, 13, s);
|
||||
|
||||
Coefficients_13_26( LARpp_j_1, LARpp_j, LARp);
|
||||
LARp_to_rp( LARp );
|
||||
FILTER( S->u, LARp, 14, s + 13);
|
||||
FILTER( S, LARp, 14, s + 13);
|
||||
|
||||
Coefficients_27_39( LARpp_j_1, LARpp_j, LARp);
|
||||
LARp_to_rp( LARp );
|
||||
FILTER( S->u, LARp, 13, s + 27);
|
||||
FILTER( S, LARp, 13, s + 27);
|
||||
|
||||
Coefficients_40_159( LARpp_j, LARp);
|
||||
LARp_to_rp( LARp );
|
||||
FILTER( S->u, LARp, 120, s + 40);
|
||||
|
||||
FILTER( S, LARp, 120, s + 40);
|
||||
}
|
||||
|
||||
void Gsm_Short_Term_Synthesis_Filter P4((S, LARcr, wt, s),
|
||||
|
||||
@@ -22,7 +22,7 @@ LIB_TARGET_DIR = .
|
||||
#
|
||||
|
||||
WARNINGS = -Wall -Wno-comment -Wno-error
|
||||
CFLAGS = -O6 -mpentium -I$(LIB_TARGET_DIR) $(WARNINGS)
|
||||
CFLAGS = -O3 -I$(LIB_TARGET_DIR) $(WARNINGS)
|
||||
|
||||
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.2 2000/01/05 08:20:39 markster
|
||||
Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 00:20:06 markster
|
||||
Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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,11 +1,8 @@
|
||||
/*
|
||||
|
||||
$Log$
|
||||
Revision 1.8 2001/04/12 21:27:53 markster
|
||||
Version 0.1.9 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.
|
||||
Revision 1.2 2000/01/05 08:20:39 markster
|
||||
Version 0.1.3 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
|
||||
@@ -32,12 +29,9 @@ 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.
|
||||
/*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
/*
|
||||
@@ -146,18 +140,18 @@ extern int placea_(integer *ipitch, integer *voibuf, integer *obound, integer *a
|
||||
/* is not altered from MAXWIN, since this would defeat the purpose */
|
||||
/* of phase-synchronous placement. */
|
||||
/* Check for case 1 and case 2 */
|
||||
allv = voibuf[((*af - 2) << 1) + 2] == 1;
|
||||
allv = allv && voibuf[((*af - 1) << 1) + 1] == 1;
|
||||
allv = allv && voibuf[((*af - 1) << 1) + 2] == 1;
|
||||
allv = voibuf[(*af - 2 << 1) + 2] == 1;
|
||||
allv = allv && voibuf[(*af - 1 << 1) + 1] == 1;
|
||||
allv = allv && voibuf[(*af - 1 << 1) + 2] == 1;
|
||||
allv = allv && voibuf[(*af << 1) + 1] == 1;
|
||||
allv = allv && voibuf[(*af << 1) + 2] == 1;
|
||||
winv = voibuf[(*af << 1) + 1] == 1 || voibuf[(*af << 1) + 2] == 1;
|
||||
if (allv || winv && *obound == 0) {
|
||||
/* APHASE: Phase synchronous window placement. */
|
||||
/* Get minimum lower index of the window. */
|
||||
i__ = (lrange + *ipitch - 1 - awin[((*af - 1) << 1) + 1]) / *ipitch;
|
||||
i__ = (lrange + *ipitch - 1 - awin[(*af - 1 << 1) + 1]) / *ipitch;
|
||||
i__ *= *ipitch;
|
||||
i__ += awin[((*af - 1) << 1) + 1];
|
||||
i__ += awin[(*af - 1 << 1) + 1];
|
||||
/* L = the actual length of this frame's analysis window. */
|
||||
l = *maxwin;
|
||||
/* Calculate the location where a perfectly centered window would star
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
/*
|
||||
|
||||
$Log$
|
||||
Revision 1.8 2001/04/12 21:27:53 markster
|
||||
Version 0.1.9 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.
|
||||
Revision 1.2 2000/01/05 08:20:39 markster
|
||||
Version 0.1.3 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
|
||||
@@ -32,12 +29,9 @@ 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.
|
||||
/*
|
||||
/* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
/* Some OSS fixes and a few lpc changes to make it actually work
|
||||
/*
|
||||
@@ -187,7 +181,7 @@ t*/
|
||||
|
||||
/* Function Body */
|
||||
/* Computing MAX */
|
||||
i__1 = vwin[((*af - 1) << 1) + 2] + 1, i__2 = (*af - 2) * *lframe + 1;
|
||||
i__1 = vwin[(*af - 1 << 1) + 2] + 1, i__2 = (*af - 2) * *lframe + 1;
|
||||
lrange = max(i__1,i__2);
|
||||
hrange = *af * *lframe;
|
||||
/* Compute OSPTR1, so the following code only looks at relevant onsets. */
|
||||
@@ -201,7 +195,7 @@ L90:
|
||||
/* Check for case 1 first (fast case): */
|
||||
if (osptr1 <= 1 || osbuf[osptr1 - 1] < lrange) {
|
||||
/* Computing MAX */
|
||||
i__1 = vwin[((*af - 1) << 1) + 2] + 1;
|
||||
i__1 = vwin[(*af - 1 << 1) + 2] + 1;
|
||||
vwin[(*af << 1) + 1] = max(i__1,*dvwinl);
|
||||
vwin[(*af << 1) + 2] = vwin[(*af << 1) + 1] + *maxwin - 1;
|
||||
*obound = 0;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
|
||||
$Log$
|
||||
Revision 1.8 2000/01/05 08:20:39 markster
|
||||
Version 0.1.9 from FTP
|
||||
Revision 1.2 2000/01/05 08:20:39 markster
|
||||
Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
Version 0.1.3 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
|
||||
@@ -44,8 +44,8 @@ static integer c__1 = 1;
|
||||
/* PREPRO Version 48 */
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
Version 0.1.3 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 integer random_(struct lpc10_decoder_state *st);
|
||||
/* RANDOM Version 49 */
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
Version 0.1.3 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 rcchk_(integer *order, real *rc1f, real *rc2f);
|
||||
/* RCCHK Version 45G */
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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.2 2000/01/05 08:20:39 markster
|
||||
Version 0.1.3 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 real c_b2 = .7f;
|
||||
/* SYNTHS Version 54 */
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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
|
||||
@@ -178,8 +178,8 @@ static real c_b2 = .7f;
|
||||
real rci[160] /* was [10][16] */;
|
||||
|
||||
/* $Log$
|
||||
* Revision 1.8 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.9 from FTP
|
||||
* Revision 1.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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
|
||||
@@ -209,8 +209,8 @@ static real c_b2 = .7f;
|
||||
/* 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.2 2000/01/05 08:20:39 markster
|
||||
* Version 0.1.3 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