Compare commits

..

3 Commits
0.1.9 ... 0.1.3

Author SHA1 Message Date
Kevin P. Fleming
836e861dde remove extraneous svn:executable properties
git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/0.1.3@7221 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-29 18:24:39 +00:00
Kevin P. Fleming
04ec7f1429 automatic tag renames
git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/0.1.3@7201 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-27 17:18:34 +00:00
Admin Commit
35e505b579 This commit was manufactured by cvs2svn to create tag 'v0-1-3'.
git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/v0-1-3@210 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-05-02 19:18:58 +00:00
208 changed files with 3219 additions and 27220 deletions

41
BUGS
View File

@@ -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
View File

@@ -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

View File

@@ -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
View File

@@ -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
View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -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 $@ $<

View File

@@ -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
View File

@@ -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;
}

View File

@@ -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

View File

@@ -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,&notime) < 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);
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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,&notime) < 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,&notime) < 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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -68,8 +68,3 @@ int usecount(void)
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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 =

View File

@@ -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(&lthread, 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))

View File

@@ -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
View 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);

View File

@@ -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
View File

@@ -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,
};

903
channel.c

File diff suppressed because it is too large Load Diff

View File

@@ -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 $@ $<

View File

@@ -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
};

View File

@@ -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 };

File diff suppressed because it is too large Load Diff

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;

File diff suppressed because it is too large Load Diff

View File

@@ -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;
}

View File

@@ -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];

View File

@@ -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

File diff suppressed because it is too large Load Diff

193
cli.c
View File

@@ -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 {

View File

@@ -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 $@ $<

View File

@@ -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
};

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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:

View File

@@ -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

View File

@@ -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)"

View File

@@ -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;

View File

@@ -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
}
}

View File

@@ -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;

View File

@@ -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 */

View File

@@ -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),

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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...

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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