]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Merge changes from team/group/appdocsxml
authorRussell Bryant <russell@russellbryant.com>
Sat, 1 Nov 2008 21:10:07 +0000 (21:10 +0000)
committerRussell Bryant <russell@russellbryant.com>
Sat, 1 Nov 2008 21:10:07 +0000 (21:10 +0000)
This commit introduces the first phase of an effort to manage documentation of the
interfaces in Asterisk in an XML format.  Currently, a new format is available for
applications and dialplan functions.  A good number of conversions to the new format
are also included.

For more information, see the following message to asterisk-dev:

http://lists.digium.com/pipermail/asterisk-dev/2008-October/034968.html

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@153365 65c4cc65-6c06-0410-ace0-fbb531ad65f3

111 files changed:
Makefile
apps/app_adsiprog.c
apps/app_alarmreceiver.c
apps/app_amd.c
apps/app_authenticate.c
apps/app_cdr.c
apps/app_chanisavail.c
apps/app_channelredirect.c
apps/app_chanspy.c
apps/app_controlplayback.c
apps/app_dahdibarge.c
apps/app_dahdiras.c
apps/app_dahdiscan.c
apps/app_dial.c
apps/app_dictate.c
apps/app_directed_pickup.c
apps/app_directory.c
apps/app_disa.c
apps/app_dumpchan.c
apps/app_echo.c
apps/app_exec.c
apps/app_fax.c
apps/app_festival.c
apps/app_getcpeid.c
apps/app_ices.c
apps/app_image.c
apps/app_jack.c
apps/app_milliwatt.c
apps/app_mixmonitor.c
apps/app_morsecode.c
apps/app_mp3.c
apps/app_nbscat.c
apps/app_page.c
apps/app_playback.c
apps/app_privacy.c
apps/app_queue.c
apps/app_readexten.c
apps/app_readfile.c
apps/app_record.c
apps/app_sayunixtime.c
apps/app_senddtmf.c
apps/app_sendtext.c
apps/app_setcallerid.c
apps/app_skel.c
apps/app_softhangup.c
apps/app_stack.c
apps/app_system.c
apps/app_talkdetect.c
apps/app_transfer.c
apps/app_url.c
apps/app_userevent.c
apps/app_verbose.c
apps/app_waituntil.c
apps/app_while.c
apps/app_zapateller.c
build_tools/get_documentation [new file with mode: 0644]
configure
configure.ac
doc/appdocsxml.dtd [new file with mode: 0644]
doc/tex/asterisk-conf.tex
funcs/func_base64.c
funcs/func_blacklist.c
funcs/func_callerid.c
funcs/func_cdr.c
funcs/func_channel.c
funcs/func_config.c
funcs/func_cut.c
funcs/func_db.c
funcs/func_devstate.c
funcs/func_dialgroup.c
funcs/func_dialplan.c
funcs/func_enum.c
funcs/func_env.c
funcs/func_extstate.c
funcs/func_global.c
funcs/func_groupcount.c
funcs/func_iconv.c
funcs/func_lock.c
funcs/func_logic.c
funcs/func_math.c
funcs/func_md5.c
funcs/func_module.c
funcs/func_odbc.c
funcs/func_rand.c
funcs/func_realtime.c
funcs/func_sha1.c
funcs/func_shell.c
funcs/func_speex.c
funcs/func_strings.c
funcs/func_timeout.c
funcs/func_uri.c
funcs/func_version.c
funcs/func_vmcount.c
funcs/func_volume.c
include/asterisk/_private.h
include/asterisk/autoconfig.h.in
include/asterisk/compat.h
include/asterisk/extconf.h
include/asterisk/module.h
include/asterisk/pbx.h
include/asterisk/strings.h
include/asterisk/term.h
include/asterisk/xml.h [new file with mode: 0644]
main/Makefile
main/asterisk.c
main/config.c
main/features.c
main/pbx.c
main/term.c
main/xml.c [new file with mode: 0644]
makeopts.in

index 7b017f22f4479f6d97fdb24bc0e9b0311f23e5c1..0521518e0b82017c8c7f1467cce8d00bc7042418 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -105,6 +105,9 @@ endif
 ASTCFLAGS+=$(COPTS)
 ASTLDFLAGS+=$(LDOPTS)
 
+# libxml2 cflags
+ASTCFLAGS+=$(LIBXML2_INCLUDE)
+
 #Uncomment this to see all build commands instead of 'quiet' output
 #NOISY_BUILD=yes
 
@@ -481,6 +484,20 @@ datafiles: _all
        mkdir -p $(DESTDIR)$(AGI_DIR)
        $(MAKE) -C sounds install
 
+documentation:
+       @echo -n "Building Documentation For: "
+       @echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" > doc/core-en_US.xml
+       @echo "<!DOCTYPE docs SYSTEM \"appdocsxml.dtd\">" >> doc/core-en_US.xml
+       @echo "<docs>" >> doc/core-en_US.xml
+       @for x in $(MOD_SUBDIRS); do \
+               echo -n "$$x " ; \
+               for i in $$x/*.c; do \
+                       $(AWK) -f build_tools/get_documentation $$i >> doc/core-en_US.xml ; \
+               done ; \
+       done
+       @echo "</docs>" >> doc/core-en_US.xml
+       @echo -e "\ndoc/core-en_US.xml --> $(ASTDATADIR)/documentation/core-en_US.xml"
+
 update: 
        @if [ -d .svn ]; then \
                echo "Updating from Subversion..." ; \
@@ -529,12 +546,16 @@ bininstall: _all installdirs $(SUBDIRS_INSTALL)
        if [ -n "$(OLDHEADERS)" ]; then \
                rm -f $(addprefix $(DESTDIR)$(ASTHEADERDIR)/,$(OLDHEADERS)) ;\
        fi
+       mkdir -p $(DESTDIR)$(ASTDATADIR)/documentation
+       mkdir -p $(DESTDIR)$(ASTDATADIR)/documentation/thirdparty
        mkdir -p $(DESTDIR)$(ASTLOGDIR)/cdr-csv
        mkdir -p $(DESTDIR)$(ASTLOGDIR)/cdr-custom
        mkdir -p $(DESTDIR)$(ASTDATADIR)/keys
        mkdir -p $(DESTDIR)$(ASTDATADIR)/firmware
        mkdir -p $(DESTDIR)$(ASTDATADIR)/firmware/iax
        mkdir -p $(DESTDIR)$(ASTMANDIR)/man8
+       $(INSTALL) -m 644 doc/core-*.xml $(ASTDATADIR)/documentation
+       $(INSTALL) -m 644 doc/appdocsxml.dtd $(ASTVARLIBDIR)/documentation
        $(INSTALL) -m 644 keys/iaxtel.pub $(DESTDIR)$(ASTDATADIR)/keys
        $(INSTALL) -m 644 keys/freeworlddialup.pub $(DESTDIR)$(ASTDATADIR)/keys
        $(INSTALL) -m 644 doc/asterisk.8 $(DESTDIR)$(ASTMANDIR)/man8
@@ -576,7 +597,7 @@ ifneq ($(findstring ~,$(DESTDIR)),)
        @exit 1
 endif
 
-install: badshell datafiles bininstall
+install: badshell datafiles documentation bininstall
        @if [ -x /usr/sbin/asterisk-post-install ]; then \
                /usr/sbin/asterisk-post-install $(DESTDIR) . ; \
        fi
@@ -656,7 +677,7 @@ samples: adsi
                echo "astrundir => $(ASTVARRUNDIR)" ; \
                echo "astlogdir => $(ASTLOGDIR)" ; \
                echo "" ; \
-               echo ";[options]" ; \
+               echo "[options]" ; \
                echo ";verbose = 3" ; \
                echo ";debug = 3" ; \
                echo ";alwaysfork = yes ; same as -F at startup" ; \
@@ -686,6 +707,7 @@ samples: adsi
                echo ";runuser = asterisk ; The user to run as" ; \
                echo ";rungroup = asterisk ; The group to run as" ; \
                echo ";lightbackground = yes ; If your terminal is set for a light-colored background" ; \
+               echo "documentation_language = en_US ; Set the Language you want Documentation displayed in. Value is in the same format as locale names" ; \
                echo "" ; \
                echo "; Changing the following lines may compromise your security." ; \
                echo ";[files]" ; \
index 255026fbd9d405d8756e9a1cf702ea4314e404f3..f35a81eea839b289c2a5d1ea844add4b964b07e2 100644 (file)
@@ -47,14 +47,24 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
 static char *app = "ADSIProg";
 
-static char *synopsis = "Load Asterisk ADSI Scripts into phone";
+/*** DOCUMENTATION
+       <application name="ADSIProg" language="en_US">
+               <synopsis>
+                       Load Asterisk ADSI Scripts into phone
+               </synopsis>
+               <syntax>
+                       <parameter name="script" required="false">
+                               <para>adsi script to use. If not given uses the default script <filename>asterisk.adsi</filename></para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>This application programs an ADSI Phone with the given script</para>
+               </description>
+       </application>
+ ***/
 
 /* #define DUMP_MESSAGES */
 
-static char *descrip =
-"  ADSIProg(script): This application programs an ADSI Phone with the given\n"
-"script. If nothing is specified, the default script (asterisk.adsi) is used.\n";
-
 struct adsi_event {
        int id;
        char *name;
@@ -1570,7 +1580,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       if (ast_register_application(app, adsi_exec, synopsis, descrip))
+       if (ast_register_application_xml(app, adsi_exec))
                return AST_MODULE_LOAD_FAILURE;
        return AST_MODULE_LOAD_SUCCESS;
 }
index db76bbdb770a5088ad2ebe65ad8522b31953b4b4..12ae49d6521a79fe1030fc38e8b23653834293a3 100644 (file)
@@ -63,18 +63,21 @@ struct event_node{
 typedef struct event_node event_node_t;
 
 static char *app = "AlarmReceiver";
-
-static char *synopsis = "Provide support for receiving alarm reports from a burglar or fire alarm panel";
-static char *descrip =
-"  AlarmReceiver(): Only 1 signalling format is supported at this time: Ademco\n"
-"Contact ID. This application should be called whenever there is an alarm\n"
-"panel calling in to dump its events. The application will handshake with the\n"
-"alarm panel, and receive events, validate them, handshake them, and store them\n"
-"until the panel hangs up. Once the panel hangs up, the application will run the\n"
-"system command specified by the eventcmd setting in alarmreceiver.conf and pipe\n"
-"the events to the standard input of the application. The configuration file also\n"
-"contains settings for DTMF timing, and for the loudness of the acknowledgement\n"
-"tones.\n";
+/*** DOCUMENTATION
+       <application name="AlarmReceiver" language="en_US">
+               <synopsis>
+                       Provide support for receiving alarm reports from a burglar or fire alarm panel
+               </synopsis>
+               <syntax />
+               <description>
+                       <para>This application should be called whenever there is an alarm panel calling in to dump its events.
+                       The application will handshake with the alarm panel, and receive events, validate them, handshake them, and store them until the panel hangs up.
+                       Once the panel hangs up, the application will run the system command specified by the eventcmd setting in <filename>alarmreceiver.conf</filename> and pipe the events to the standard input of the application. 
+                       The configuration file also contains settings for DTMF timing, and for the loudness of the acknowledgement tones.</para>
+                       <note><para>Only 1 signalling format is supported at this time: Ademco Contact ID.</para></note>
+               </description>
+       </application>
+ ***/
 
 /* Config Variables */
 static int fdtimeout = 2000;
@@ -711,7 +714,7 @@ static int unload_module(void)
 static int load_module(void)
 {
        if (load_config()) {
-               if (ast_register_application(app, alarmreceiver_exec, synopsis, descrip))
+               if (ast_register_application_xml(app, alarmreceiver_exec))
                        return AST_MODULE_LOAD_FAILURE;
                return AST_MODULE_LOAD_SUCCESS;
        } else
index 81298f4009e342093049fb02259f6990f713ba56..bf3603b3e67a9a1223fd02517b139d2acd75a8d3 100644 (file)
@@ -39,45 +39,88 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/config.h"
 #include "asterisk/app.h"
 
+/*** DOCUMENTATION
+       <application name="AMD" language="en_US">
+               <synopsis>
+                       Attempt to detect answering machines.
+               </synopsis>
+               <syntax>
+                       <parameter name="initialSilence" required="false">
+                               <para>Is maximum initial silence duration before greeting.</para>
+                               <para>If this is exceeded set as MACHINE</para>
+                       </parameter>
+                       <parameter name="greeting" required="false">
+                               <para>is the maximum length of a greeting.</para>
+                               <para>If this is exceeded set as MACHINE</para>
+                       </parameter>
+                       <parameter name="afterGreetingSilence" required="false">
+                               <para>Is the silence after detecting a greeting.</para>
+                               <para>If this is exceeded set as HUMAN</para>
+                       </parameter>
+                       <parameter name="totalAnalysis Time" required="false">
+                               <para>Is the maximum time allowed for the algorithm</para>
+                               <para>to decide HUMAN or MACHINE</para>
+                       </parameter>
+                       <parameter name="miniumWordLength" required="false">
+                               <para>Is the minimum duration of Voice considered to be a word</para>
+                       </parameter>
+                       <parameter name="betweenWordSilence" required="false">
+                               <para>Is the minimum duration of silence after a word to
+                               consider the audio that follows to be a new word</para>
+                       </parameter>
+                       <parameter name="maximumNumberOfWords" required="false">
+                               <para>Is the maximum number of words in a greeting</para>
+                               <para>If this is exceeded set as MACHINE</para>
+                       </parameter>
+                       <parameter name="silenceThreshold" required="false">
+                               <para>How long do we consider silence</para>
+                       </parameter>
+                       <parameter name="maximumWordLength" required="false">
+                               <para>Is the maximum duration of a word to accept.</para>
+                               <para>If exceeded set as MACHINE</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>This application attempts to detect answering machines at the beginning
+                       of outbound calls. Simply call this application after the call
+                       has been answered (outbound only, of course).</para>
+                       <para>When loaded, AMD reads amd.conf and uses the parameters specified as
+                       default values. Those default values get overwritten when the calling AMD
+                       with parameters.</para>
+                       <para>This application sets the following channel variables:</para>
+                       <variablelist>
+                               <variable name="AMDSTATUS">
+                                       <para>This is the status of the answering machine detection</para>
+                                       <value name="MACHINE" />
+                                       <value name="HUMAN" />
+                                       <value name="NOTSURE" />
+                                       <value name="HANGUP" />
+                               </variable>
+                               <variable name="AMDCAUSE">
+                                       <para>Indicates the cause that led to the conclusion</para>
+                                       <value name="TOOLONG">
+                                               Total Time.
+                                       </value>
+                                       <value name="INITIALSILENCE">
+                                               Silence Duration - Initial Silence.
+                                       </value>
+                                       <value name="HUMAN">
+                                               Silence Duration - afterGreetingSilence.
+                                       </value>
+                                       <value name="LONGGREETING">
+                                               Voice Duration - Greeting.
+                                       </value>
+                                       <value name="MAXWORDLENGTH">
+                                               Word Count - maximum number of words.
+                                       </value>        
+                               </variable>
+                       </variablelist>
+               </description>
+       </application>
+
+ ***/
 
 static char *app = "AMD";
-static char *synopsis = "Attempts to detect answering machines";
-static char *descrip =
-"  AMD([initialSilence],[greeting],[afterGreetingSilence],[totalAnalysisTime]\n"
-"      ,[minimumWordLength],[betweenWordsSilence],[maximumNumberOfWords]\n"
-"      ,[silenceThreshold],[|maximumWordLength])\n"
-"  This application attempts to detect answering machines at the beginning\n"
-"  of outbound calls.  Simply call this application after the call\n"
-"  has been answered (outbound only, of course).\n"
-"  When loaded, AMD reads amd.conf and uses the parameters specified as\n"
-"  default values. Those default values get overwritten when calling AMD\n"
-"  with parameters.\n"
-"- 'initialSilence' is the maximum silence duration before the greeting. If\n"
-"   exceeded then MACHINE.\n"
-"- 'greeting' is the maximum length of a greeting. If exceeded then MACHINE.\n"
-"- 'afterGreetingSilence' is the silence after detecting a greeting.\n"
-"   If exceeded then HUMAN.\n"
-"- 'totalAnalysisTime' is the maximum time allowed for the algorithm to decide\n"
-"   on a HUMAN or MACHINE.\n"
-"- 'minimumWordLength'is the minimum duration of Voice to considered as a word.\n"
-"- 'betweenWordsSilence' is the minimum duration of silence after a word to \n"
-"   consider the audio that follows as a new word.\n"
-"- 'maximumNumberOfWords'is the maximum number of words in the greeting. \n"
-"   If exceeded then MACHINE.\n"
-"- 'silenceThreshold' is the silence threshold.\n"
-"- 'maximumWordLength' is the maximum duration of a word to accept. If exceeded then MACHINE\n"
-"This application sets the following channel variables upon completion:\n"
-"    AMDSTATUS - This is the status of the answering machine detection.\n"
-"                Possible values are:\n"
-"                MACHINE | HUMAN | NOTSURE | HANGUP\n"
-"    AMDCAUSE - Indicates the cause that led to the conclusion.\n"
-"               Possible values are:\n"
-"               TOOLONG-<%d total_time>\n"
-"               INITIALSILENCE-<%d silenceDuration>-<%d initialSilence>\n"
-"               HUMAN-<%d silenceDuration>-<%d afterGreetingSilence>\n"
-"               MAXWORDS-<%d wordsCount>-<%d maximumNumberOfWords>\n"
-"               LONGGREETING-<%d voiceDuration>-<%d greeting>\n"
-"               MAXWORDLENGTH-<%d consecutiveVoiceDuration>\n";
 
 #define STATE_IN_WORD       1
 #define STATE_IN_SILENCE    2
@@ -437,7 +480,7 @@ static int load_module(void)
 {
        if (load_config(0))
                return AST_MODULE_LOAD_DECLINE;
-       if (ast_register_application(app, amd_exec, synopsis, descrip))
+       if (ast_register_application_xml(app, amd_exec))
                return AST_MODULE_LOAD_FAILURE;
        return AST_MODULE_LOAD_SUCCESS;
 }
index 1bdc1153ba5176ca1c76302d91e5efc6bbe9c1a8..10d0b2f7342a4e44191140e7cd404ffa505594f8 100644 (file)
@@ -54,31 +54,52 @@ AST_APP_OPTIONS(auth_app_options, {
 
 
 static char *app = "Authenticate";
-
-static char *synopsis = "Authenticate a user";
-
-static char *descrip =
-"  Authenticate(password[,options[,maxdigits[,prompt]]]): This application asks the caller\n"
-"to enter a given password in order to continue dialplan execution. If the password\n"
-"begins with the '/' character, it is interpreted as a file which contains a list of\n"
-"valid passwords, listed 1 password per line in the file.\n"
-"  When using a database key, the value associated with the key can be anything.\n"
-"Users have three attempts to authenticate before the channel is hung up.\n"
-"  Options:\n"
-"     a - Set the channels' account code to the password that is entered\n"
-"     d - Interpret the given path as database key, not a literal file\n"
-"     m - Interpret the given path as a file which contains a list of account\n"
-"         codes and password hashes delimited with ':', listed one per line in\n"
-"         the file. When one of the passwords is matched, the channel will have\n"
-"         its account code set to the corresponding account code in the file.\n"
-"     r - Remove the database key upon successful entry (valid with 'd' only)\n"
-"     maxdigits  - maximum acceptable number of digits. Stops reading after\n"
-"         maxdigits have been entered (without requiring the user to\n"
-"         press the '#' key).\n"
-"         Defaults to 0 - no limit - wait for the user press the '#' key.\n"
-"     prompt - Override the agent-pass prompt file.\n"
- ;
-;
+/*** DOCUMENTATION
+       <application name="Authenticate" language="en_US">
+               <synopsis>
+                       Authenticate a user
+               </synopsis>
+               <syntax>
+                       <parameter name="password" required="true">
+                               <para>Password the user should know</para>
+                       </parameter>
+                       <parameter name="options" required="false">
+                               <optionlist>
+                                       <option name="a">
+                                               <para>Set the channels' account code to the password that is entered</para>
+                                       </option>
+                                       <option name="d">
+                                               <para>Interpret the given path as database key, not a literal file</para>
+                                       </option>
+                                       <option name="m">
+                                               <para>Interpret the given path as a file which contains a list of account
+                                               codes and password hashes delimited with <literal>:</literal>, listed one per line in
+                                               the file. When one of the passwords is matched, the channel will have
+                                               its account code set to the corresponding account code in the file.</para>
+                                       </option>
+                                       <option name="r">
+                                               <para>Remove the database key upon successful entry (valid with <literal>d</literal> only)</para>
+                                       </option>
+                               </optionlist>
+                       </parameter>
+                       <parameter name="maxdigits" required="false">
+                               <para>maximum acceptable number of digits. Stops reading after
+                               maxdigits have been entered (without requiring the user to press the <literal>#</literal> key).
+                               Defaults to 0 - no limit - wait for the user press the <literal>#</literal> key.</para>
+                       </parameter>
+                       <parameter name="prompt" required="false">
+                               <para>Override the agent-pass prompt file.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>This application asks the caller to enter a given password in order to continue dialplan execution.</para>
+                       <para>If the password begins with the <literal>/</literal> character, 
+                       it is interpreted as a file which contains a list of valid passwords, listed 1 password per line in the file.</para>
+                       <para>When using a database key, the value associated with the key can be anything.</para>
+                       <para>Users have three attempts to authenticate before the channel is hung up.</para>
+               </description>
+       </application>
+ ***/
 
 static int auth_exec(struct ast_channel *chan, void *data)
 {
@@ -225,7 +246,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       if (ast_register_application(app, auth_exec, synopsis, descrip))
+       if (ast_register_application_xml(app, auth_exec))
                return AST_MODULE_LOAD_FAILURE;
        return AST_MODULE_LOAD_SUCCESS;
 }
index 038b0a32f872c0f89fcb9b88e6166d134dc41aff..ca228da03b9766d69cc97f120efee9267dc5e7d6 100644 (file)
@@ -32,13 +32,19 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/channel.h"
 #include "asterisk/module.h"
 
-static char *nocdr_descrip =
-"  NoCDR(): This application will tell Asterisk not to maintain a CDR for the\n"
-"current call.\n";
+/*** DOCUMENTATION
+       <application name="NoCDR" language="en_US">
+               <synopsis>
+                       Tell Asterisk to not maintain a CDR for the current call
+               </synopsis>
+               <syntax />
+               <description>
+                       <para>This application will tell Asterisk not to maintain a CDR for the current call.</para>
+               </description>
+       </application>
+ ***/
 
 static char *nocdr_app = "NoCDR";
-static char *nocdr_synopsis = "Tell Asterisk to not maintain a CDR for the current call";
-
 
 static int nocdr_exec(struct ast_channel *chan, void *data)
 {
@@ -55,7 +61,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       if (ast_register_application(nocdr_app, nocdr_exec, nocdr_synopsis, nocdr_descrip))
+       if (ast_register_application_xml(nocdr_app, nocdr_exec))
                return AST_MODULE_LOAD_FAILURE;
        return AST_MODULE_LOAD_SUCCESS;
 }
index 68cab31aac3beb22257f72132ae3bab4121bafcc..bc1adcc791cce7c8636ead33b2119bf36f098b8c 100644 (file)
@@ -43,22 +43,54 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
 static char *app = "ChanIsAvail";
 
-static char *synopsis = "Check channel availability";
-
-static char *descrip =
-"  ChanIsAvail(Technology/resource[&Technology2/resource2...][,options]): \n"
-"This application will check to see if any of the specified channels are\n"
-"available.\n"
-"  Options:\n"
-"    a - Check for all available channels, not only the first one.\n"
-"    s - Consider the channel unavailable if the channel is in use at all.\n"
-"    t - Simply checks if specified channels exist in the channel list\n"
-"        (implies option s).\n"
-"This application sets the following channel variable upon completion:\n"
-"  AVAILCHAN     - the name of the available channel, if one exists\n"
-"  AVAILORIGCHAN - the canonical channel name that was used to create the channel\n"
-"  AVAILSTATUS   - the status code for the available channel\n";
-
+/*** DOCUMENTATION
+       <application name="ChanIsAvail" language="en_US">
+               <synopsis>
+                       Check channel availability
+               </synopsis>
+               <syntax>
+                       <parameter name="Technology/Resource" required="true" argsep="&amp;">
+                               <argument name="Technology2/Resource2" multiple="true">
+                                       <para>Optional extra devices to check</para>
+                                       <para>If you need more then one enter them as
+                                       Technology2/Resource2&amp;Technology3/Resourse3&amp;.....</para>
+                               </argument>
+                               <para>Specification of the device(s) to check.  These must be in the format of 
+                               <literal>Technology/Resource</literal>, where <replaceable>Technology</replaceable>
+                               represents a particular channel driver, and <replaceable>Resource</replaceable>
+                               represents a resource available to that particular channel driver.</para>
+                       </parameter>
+                       <parameter name="options" required="false">
+                               <optionlist>
+                                       <option name="a">
+                                               <para>Check for all available channels, not only the first one</para>
+                                       </option>
+                                       <option name="s">
+                                               <para>Consider the channel unavailable if the channel is in use at all</para>
+                                       </option>
+                                       <option name="t" implies="s">
+                                               <para>Simply checks if specified channels exist in the channel list</para>
+                                       </option>
+                               </optionlist>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>This application will check to see if any of the specified channels are available.</para>
+                       <para>This application sets the following channel variables:</para>
+                       <variablelist>
+                               <variable name="AVAILCHAN">
+                                       <para>The name of the available channel, if one exists</para>
+                               </variable>
+                               <variable name="AVAILORIGCHAN">
+                                       <para>The canonical channel name that was used to create the channel</para>
+                               </variable>
+                               <variable name="AVAILSTATUS">
+                                       <para>The status code for the available channel</para>
+                               </variable>
+                       </variablelist>
+               </description>
+       </application>
+ ***/
 
 static int chanavail_exec(struct ast_channel *chan, void *data)
 {
@@ -165,7 +197,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       return ast_register_application(app, chanavail_exec, synopsis, descrip) ?
+       return ast_register_application_xml(app, chanavail_exec) ?
                AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS;
 }
 
index 610f254df2efac1cdad5ab30d886659d31fe30aa..f89c45225f998676b5cf8d205d199a99e6c33ff6 100644 (file)
@@ -35,14 +35,32 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/app.h"
 #include "asterisk/features.h"
 
+/*** DOCUMENTATION
+       <application name="ChannelRedirect" language="en_US">
+               <synopsis>
+                       Redirects given channel to a dialplan target
+               </synopsis>
+               <syntax>
+                       <parameter name="channel" required="true" />
+                       <parameter name="context" required="false" />
+                       <parameter name="extension" required="false" />
+                       <parameter name="priority" required="true" />
+               </syntax>
+               <description>
+                       <para>Sends the specified channel to the specified extension priority</para>
+
+                       <para>This application sets the following channel variables upon completion</para>
+                       <variablelist>
+                               <variable name="CHANNELREDIRECT_STATUS">
+                                       <value name="NOCHANNEL" />
+                                       <value name="SUCCESS" />
+                                       <para>Are set to the result of the redirection</para>
+                               </variable>
+                       </variablelist>
+               </description>
+       </application>
+ ***/
 static char *app = "ChannelRedirect";
-static char *synopsis = "Redirects given channel to a dialplan target.";
-static char *descrip =
-"ChannelRedirect(channel,[[context,]extension,]priority)\n"
-"  Sends the specified channel to the specified extension priority\n"
-"This application sets the following channel variables upon completion:\n"
-"  CHANNELREDIRECT_STATUS - Are set to the result of the redirection\n"
-"                           either NOCHANNEL or SUCCESS\n";
 
 static int asyncgoto_exec(struct ast_channel *chan, void *data)
 {
@@ -89,7 +107,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       return ast_register_application(app, asyncgoto_exec, synopsis, descrip) ?
+       return ast_register_application_xml(app, asyncgoto_exec) ?
                AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS;
 }
 
index dea2017eac865cde63001d0ebd12e192e10f1fe3..92a43054621616d6d4a0105973b14f9fe2f24bde 100644 (file)
@@ -52,128 +52,238 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #define AST_NAME_STRLEN 256
 #define NUM_SPYGROUPS 128
 
-static const char *tdesc = "Listen to a channel, and optionally whisper into it";
+/*** DOCUMENTATION
+       <application name="ChanSpy" language="en_US">
+               <synopsis>
+                       Listen to a channel, and optionally whisper into it.
+               </synopsis>
+               <syntax>
+                       <parameter name="chanprefix" />
+                       <parameter name="options">
+                               <optionlist>
+                                       <option name="b">
+                                               <para>Only spy on channels involved in a bridged call.</para>
+                                       </option>
+                                       <option name="B">
+                                               <para>Instead of whispering on a single channel barge in on both
+                                               channels involved in the call.</para>
+                                       </option>
+                                       <option name="d">
+                                               <para>Override the typical numeric DTMF functionality and instead
+                                               use DTMF to switch between spy modes.</para>
+                                               <enumlist>
+                                                       <enum name="4">
+                                                               <para>spy mode</para>
+                                                       </enum>
+                                                       <enum name="5">
+                                                               <para>whisper mode</para>
+                                                       </enum>
+                                                       <enum name="6">
+                                                               <para>barge mode</para>
+                                                       </enum>
+                                               </enumlist>
+                                       </option>
+                                       <option name="g">
+                                               <argument name="grp" required="true">
+                                                       <para>Only spy on channels in which one or more of the groups
+                                                       listed in <replaceable>grp</replaceable> matches one or more groups from the
+                                                       <variable>SPYGROUP</variable> variable set on the channel to be spied upon.</para>
+                                               </argument>
+                                               <note><para>both <replaceable>grp</replaceable> and <variable>SPYGROUP</variable> can contain 
+                                               either a single group or a colon-delimited list of groups, such
+                                               as <literal>sales:support:accounting</literal>.</para></note>
+                                       </option>
+                                       <option name="n" argsep="@">
+                                               <para>Say the name of the person being spied on if that person has recorded
+                                               his/her name. If a context is specified, then that voicemail context will
+                                               be searched when retrieving the name, otherwise the <literal>default</literal> context
+                                               be used when searching for the name (i.e. if SIP/1000 is the channel being
+                                               spied on and no mailbox is specified, then <literal>1000</literal> will be used when searching
+                                               for the name).</para>
+                                               <argument name="mailbox" />
+                                               <argument name="context" />
+                                       </option>
+                                       <option name="q">
+                                               <para>Don't play a beep when beginning to spy on a channel, or speak the
+                                               selected channel name.</para>
+                                       </option>
+                                       <option name="r">
+                                               <para>Record the session to the monitor spool directory. An optional base for the filename 
+                                               may be specified. The default is <literal>chanspy</literal>.</para>
+                                               <argument name="basename" />
+                                       </option>
+                                       <option name="s">
+                                               <para>Skip the playback of the channel type (i.e. SIP, IAX, etc) when
+                                               speaking the selected channel name.</para>
+                                       </option>
+                                       <option name="v">
+                                               <argument name="value" />
+                                               <para>Adjust the initial volume in the range from <literal>-4</literal> 
+                                               to <literal>4</literal>. A negative value refers to a quieter setting.</para>
+                                       </option>
+                                       <option name="w">
+                                               <para>Enable <literal>whisper</literal> mode, so the spying channel can talk to
+                                               the spied-on channel.</para>
+                                       </option>
+                                       <option name="W">
+                                               <para>Enable <literal>private whisper</literal> mode, so the spying channel can
+                                               talk to the spied-on channel but cannot listen to that channel.</para>
+                                       </option>
+                                       <option name="o">
+                                               <para>Only listen to audio coming from this channel.</para>
+                                       </option>
+                                       <option name="X">
+                                               <para>Allow the user to exit ChanSpy to a valid single digit
+                                               numeric extension in the current context or the context
+                                               specified by the <variable>SPY_EXIT_CONTEXT</variable> channel variable. The
+                                               name of the last channel that was spied on will be stored
+                                               in the <variable>SPY_CHANNEL</variable> variable.</para>
+                                       </option>
+                                       <option name="e">
+                                               <argument name="ext" required="true" />
+                                               <para>Enable <emphasis>enforced</emphasis> mode, so the spying channel can
+                                               only monitor extensions whose name is in the <replaceable>ext</replaceable> : delimited 
+                                               list.</para>
+                                       </option>
+                               </optionlist>           
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>This application is used to listen to the audio from an Asterisk channel. This includes the audio 
+                       coming in and "out of the channel being spied on. If the <literal>chanprefix</literal> parameter is specified,
+                       only channels beginning with this string will be spied upon.</para>
+                       <para>While spying, the following actions may be performed:</para>
+                       <para> - Dialing <literal>#</literal> cycles the volume level.</para>
+                       <para> - Dialing <literal>*</literal> will stop spying and look for another channel to spy on.</para>
+                       <para> - Dialing a series of digits followed by <literal>#</literal> builds a channel name to append
+                       to 'chanprefix'. For example, executing ChanSpy(Agent) and then dialing the digits '1234#' 
+                       while spying will begin spying on the channel 'Agent/1234'. Note that this feature will be overriden if the 'd' option
+                       is used</para>
+                       <note><para>The <replaceable>X</replaceable> option supersedes the three features above in that if a valid
+                       single digit extension exists in the correct context ChanSpy will exit to it.
+                       This also disables choosing a channel based on <literal>chanprefix</literal> and a digit sequence.</para></note>
+               </description>
+       </application>
+       <application name="ExtenSpy" language="en_US">
+               <synopsis>
+                       Listen to a channel, and optionally whisper into it.
+               </synopsis>
+               <syntax>
+                       <parameter name="exten" required="true" argsep="@">
+                               <argument name="exten" required="true">
+                                       <para>Specify extension.</para>
+                               </argument>
+                               <argument name="context">
+                                       <para>Optionally specify a context, defaults to <literal>default</literal>.</para>
+                               </argument>
+                       </parameter>
+                       <parameter name="options">
+                               <optionlist>
+                                       <option name="b">
+                                               <para>Only spy on channels involved in a bridged call.</para>
+                                       </option>
+                                       <option name="B">
+                                               <para>Instead of whispering on a single channel barge in on both
+                                               channels involved in the call.</para>
+                                       </option>
+                                       <option name="d">
+                                               <para>Override the typical numeric DTMF functionality and instead
+                                               use DTMF to switch between spy modes.</para>
+                                               <enumlist>
+                                                       <enum name="4">
+                                                               <para>spy mode</para>
+                                                       </enum>
+                                                       <enum name="5">
+                                                               <para>whisper mode</para>
+                                                       </enum>
+                                                       <enum name="6">
+                                                               <para>barge mode</para>
+                                                       </enum>
+                                               </enumlist>
+                                       </option>
+                                       <option name="g">
+                                               <argument name="grp" required="true">
+                                                       <para>Only spy on channels in which one or more of the groups
+                                                       listed in <replaceable>grp</replaceable> matches one or more groups from the
+                                                       <variable>SPYGROUP</variable> variable set on the channel to be spied upon.</para>
+                                               </argument>
+                                               <note><para>both <replaceable>grp</replaceable> and <variable>SPYGROUP</variable> can contain 
+                                               either a single group or a colon-delimited list of groups, such
+                                               as <literal>sales:support:accounting</literal>.</para></note>
+                                       </option>
+                                       <option name="n" argsep="@">
+                                               <para>Say the name of the person being spied on if that person has recorded
+                                               his/her name. If a context is specified, then that voicemail context will
+                                               be searched when retrieving the name, otherwise the <literal>default</literal> context
+                                               be used when searching for the name (i.e. if SIP/1000 is the channel being
+                                               spied on and no mailbox is specified, then <literal>1000</literal> will be used when searching
+                                               for the name).</para>
+                                               <argument name="mailbox" />
+                                               <argument name="context" />
+                                       </option>
+                                       <option name="q">
+                                               <para>Don't play a beep when beginning to spy on a channel, or speak the
+                                               selected channel name.</para>
+                                       </option>
+                                       <option name="r">
+                                               <para>Record the session to the monitor spool directory. An optional base for the filename 
+                                               may be specified. The default is <literal>chanspy</literal>.</para>
+                                               <argument name="basename" />
+                                       </option>
+                                       <option name="s">
+                                               <para>Skip the playback of the channel type (i.e. SIP, IAX, etc) when
+                                               speaking the selected channel name.</para>
+                                       </option>
+                                       <option name="v">
+                                               <argument name="value" />
+                                               <para>Adjust the initial volume in the range from <literal>-4</literal> 
+                                               to <literal>4</literal>. A negative value refers to a quieter setting.</para>
+                                       </option>
+                                       <option name="w">
+                                               <para>Enable <literal>whisper</literal> mode, so the spying channel can talk to
+                                               the spied-on channel.</para>
+                                       </option>
+                                       <option name="W">
+                                               <para>Enable <literal>private whisper</literal> mode, so the spying channel can
+                                               talk to the spied-on channel but cannot listen to that channel.</para>
+                                       </option>
+                                       <option name="o">
+                                               <para>Only listen to audio coming from this channel.</para>
+                                       </option>
+                                       <option name="X">
+                                               <para>Allow the user to exit ChanSpy to a valid single digit
+                                               numeric extension in the current context or the context
+                                               specified by the <variable>SPY_EXIT_CONTEXT</variable> channel variable. The
+                                               name of the last channel that was spied on will be stored
+                                               in the <variable>SPY_CHANNEL</variable> variable.</para>
+                                       </option>
+                                       <option name="e">
+                                               <argument name="ext" required="true" />
+                                               <para>Enable <emphasis>enforced</emphasis> mode, so the spying channel can
+                                               only monitor extensions whose name is in the <replaceable>ext</replaceable> : delimited 
+                                               list.</para>
+                                       </option>
+                               </optionlist>   
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>This application is used to listen to the audio from an Asterisk channel. This includes 
+                       the audio coming in and out of the channel being spied on. Only channels created by outgoing calls for the
+                       specified extension will be selected for spying. If the optional context is not supplied, 
+                       the current channel's context will be used.</para>
+                       <para>While spying, the following actions may be performed:</para>
+                       <para> - Dialing <literal>#</literal> cycles the volume level.</para>
+                        <para> - Dialing <literal>*</literal> will stop spying and look for another channel to spy on.</para>
+                       <note><para>The <replaceable>X</replaceable> option supersedes the three features above in that if a valid
+                       single digit extension exists in the correct context ChanSpy will exit to it.
+                       This also disables choosing a channel based on <literal>chanprefix</literal> and a digit sequence.</para></note>
+               </description>
+       </application>
+
+ ***/
 static const char *app_chan = "ChanSpy";
-static const char *desc_chan =
-"  ChanSpy([chanprefix][,options]): This application is used to listen to the\n"
-"audio from an Asterisk channel. This includes the audio coming in and\n"
-"out of the channel being spied on. If the 'chanprefix' parameter is specified,\n"
-"only channels beginning with this string will be spied upon.\n"
-"  While spying, the following actions may be performed:\n"
-"    - Dialing # cycles the volume level.\n"
-"    - Dialing * will stop spying and look for another channel to spy on.\n"
-"    - Dialing a series of digits followed by # builds a channel name to append\n"
-"      to 'chanprefix'. For example, executing ChanSpy(Agent) and then dialing\n"
-"      the digits '1234#' while spying will begin spying on the channel\n"
-"      'Agent/1234'. Note that this feature will be overriden if the 'd' option\n"
-"       is used\n"
-"  Note: The X option supersedes the three features above in that if a valid\n"
-"        single digit extension exists in the correct context ChanSpy will\n"
-"        exit to it. This also disables choosing a channel based on 'chanprefix'\n"
-"        and a digit sequence.\n"
-"  Options:\n"
-"    b                      - Only spy on channels involved in a bridged call.\n"
-"    B                      - Instead of whispering on a single channel barge in on both\n"
-"                             channels involved in the call.\n"
-"    d                      - Override the typical numeric DTMF functionality and instead\n"
-"                             use DTMF to switch between spy modes.\n"
-"                                     4 = spy mode\n"
-"                                     5 = whisper mode\n"
-"                                     6 = barge mode\n"
-"    g(grp)                 - Only spy on channels in which one or more of the groups \n"
-"                             listed in 'grp' matches one or more groups from the\n"
-"                             SPYGROUP variable set on the channel to be spied upon.\n"
-"                             Note that both 'grp' and SPYGROUP can contain either a\n"
-"                             single group or a colon-delimited list of groups, such\n"
-"                             as 'sales:support:accounting'.\n"
-"    n([mailbox][@context]) - Say the name of the person being spied on if that person has recorded\n"
-"                             his/her name. If a context is specified, then that voicemail context will\n"
-"                             be searched when retrieving the name, otherwise the \"default\" context\n"
-"                             will be searched. If no mailbox is specified, then the channel name will\n"
-"                             be used when searching for the name (i.e. if SIP/1000 is the channel being\n"
-"                             spied on and no mailbox is specified, then \"1000\" will be used when searching\n"
-"                             for the name).\n"
-"    q                      - Don't play a beep when beginning to spy on a channel, or speak the\n"
-"                             selected channel name.\n"
-"    r[(basename)]          - Record the session to the monitor spool directory. An\n"
-"                             optional base for the filename may be specified. The\n"
-"                             default is 'chanspy'.\n"
-"    s                      - Skip the playback of the channel type (i.e. SIP, IAX, etc) when\n"
-"                             speaking the selected channel name.\n"
-"    v([value])             - Adjust the initial volume in the range from -4 to 4. A\n"
-"                             negative value refers to a quieter setting.\n"
-"    w                      - Enable 'whisper' mode, so the spying channel can talk to\n"
-"                             the spied-on channel.\n"
-"    W                      - Enable 'private whisper' mode, so the spying channel can\n"
-"                             talk to the spied-on channel but cannot listen to that\n"
-"                             channel.\n"
-"    o                      - Only listen to audio coming from this channel.\n"
-"    X                      - Allow the user to exit ChanSpy to a valid single digit\n"
-"                             numeric extension in the current context or the context\n"
-"                             specified by the SPY_EXIT_CONTEXT channel variable. The\n"
-"                             name of the last channel that was spied on will be stored\n"
-"                             in the SPY_CHANNEL variable.\n"
-"    e(ext)                 - Enable 'enforced' mode, so the spying channel can\n"
-"                             only monitor extensions whose name is in the 'ext' : \n"
-"                             delimited list.\n"
-;
 
 static const char *app_ext = "ExtenSpy";
-static const char *desc_ext =
-"  ExtenSpy(exten[@context][,options]): This application is used to listen to the\n"
-"audio from an Asterisk channel. This includes the audio coming in and\n"
-"out of the channel being spied on. Only channels created by outgoing calls for the\n"
-"specified extension will be selected for spying. If the optional context is not\n"
-"supplied, the current channel's context will be used.\n"
-"  While spying, the following actions may be performed:\n"
-"    - Dialing # cycles the volume level.\n"
-"    - Dialing * will stop spying and look for another channel to spy on.\n"
-"  Note: The X option superseeds the two features above in that if a valid\n"
-"        single digit extension exists in the correct context it ChanSpy will\n"
-"        exit to it.\n"
-"  Options:\n"
-"    b                      - Only spy on channels involved in a bridged call.\n"
-"    B                      - Instead of whispering on a single channel barge in on both\n"
-"                             channels involved in the call.\n"
-"    d                      - Override the typical numeric DTMF functionality and instead\n"
-"                             use DTMF to switch between spy modes.\n"
-"                                     4 = spy mode\n"
-"                                     5 = whisper mode\n"
-"                                     6 = barge mode\n"
-"    g(grp)                 - Only spy on channels in which one or more of the groups \n"
-"                             listed in 'grp' matches one or more groups from the\n"
-"                             SPYGROUP variable set on the channel to be spied upon.\n"
-"                             Note that both 'grp' and SPYGROUP can contain either a\n"
-"                             single group or a colon-delimited list of groups, such\n"
-"                             as 'sales:support:accounting'.\n"
-"    n([mailbox][@context]) - Say the name of the person being spied on if that person has recorded\n"
-"                             his/her name. If a context is specified, then that voicemail context will\n"
-"                             be searched when retrieving the name, otherwise the \"default\" context\n"
-"                             will be searched. If no mailbox is specified, then the channel name will\n"
-"                             be used when searching for the name (i.e. if SIP/1000 is the channel being\n"
-"                             spied on and no mailbox is specified, then \"1000\" will be used when searching\n"
-"                             for the name).\n"
-"    q                      - Don't play a beep when beginning to spy on a channel, or speak the\n"
-"                             selected channel name.\n"
-"    r[(basename)]          - Record the session to the monitor spool directory. An\n"
-"                             optional base for the filename may be specified. The\n"
-"                             default is 'chanspy'.\n"
-"    s                      - Skip the playback of the channel type (i.e. SIP, IAX, etc) when\n"
-"                             speaking the selected channel name.\n"
-"    v([value])             - Adjust the initial volume in the range from -4 to 4. A\n"
-"                             negative value refers to a quieter setting.\n"
-"    w                      - Enable 'whisper' mode, so the spying channel can talk to\n"
-"                             the spied-on channel.\n"
-"    W                      - Enable 'private whisper' mode, so the spying channel can\n"
-"                             talk to the spied-on channel but cannot listen to that\n"
-"                             channel.\n"
-"    o                      - Only listen to audio coming from this channel.\n"
-"    X                      - Allow the user to exit ChanSpy to a valid single digit\n"
-"                             numeric extension in the current context or the context\n"
-"                             specified by the SPY_EXIT_CONTEXT channel variable. The\n"
-"                             name of the last channel that was spied on will be stored\n"
-"                             in the SPY_CHANNEL variable.\n"
-;
 
 enum {
        OPTION_QUIET             = (1 << 0),    /* Quiet, no announcement */
@@ -1103,8 +1213,8 @@ static int load_module(void)
 {
        int res = 0;
 
-       res |= ast_register_application(app_chan, chanspy_exec, tdesc, desc_chan);
-       res |= ast_register_application(app_ext, extenspy_exec, tdesc, desc_ext);
+       res |= ast_register_application_xml(app_chan, chanspy_exec);
+       res |= ast_register_application_xml(app_ext, extenspy_exec);
 
        return res;
 }
index f79ab6d42a3857991e6328f0872c6dd01d7101d7..4d7432d9cd6e3c439dd0e470cdeab894de33630c 100644 (file)
@@ -33,32 +33,67 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/app.h"
 #include "asterisk/module.h"
 
+/*** DOCUMENTATION
+       <application name="ControlPlayback" language="en_US">
+               <synopsis>
+                       Play a file with fast forward and rewind.
+               </synopsis>
+               <syntax>
+                       <parameter name="filename" required="true" />
+                       <parameter name="skipms">
+                               <para>This is number of milliseconds to skip when rewinding or
+                               fast-forwarding.</para>
+                       </parameter>
+                       <parameter name="ff">
+                               <para>Fast-forward when this DTMF digit is received. (defaults to <literal>#</literal>)</para>
+                       </parameter>
+                       <parameter name="rew">
+                               <para>Rewind when this DTMF digit is received. (defaults to <literal>*</literal>)</para>
+                       </parameter>
+                       <parameter name="stop">
+                               <para>Stop playback when this DTMF digit is received.</para>
+                       </parameter>
+                       <parameter name="pause">
+                               <para>Pause playback when this DTMF digit is received.</para>
+                       </parameter>
+                       <parameter name="restart">
+                               <para>Restart playback when this DTMF digit is received.</para>
+                       </parameter>
+                       <parameter name="options">
+                               <optionlist>
+                                       <option name="o">
+                                               <argument name="time" required="true">
+                                                       <para>Start at <replaceable>time</replaceable> ms from the
+                                                       beginning of the file.</para>
+                                               </argument>
+                                       </option>
+                               </optionlist>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>This application will play back the given <replaceable>filename</replaceable>.</para>
+                       <para>It sets the following channel variables upon completion:</para>
+                       <variablelist>
+                               <variable name="CPLAYBACKSTATUS">
+                                       <para>Contains the status of the attempt as a text string</para>
+                                       <value name="SUCCESS" />
+                                       <value name="USERSTOPPED" />
+                                       <value name="ERROR" />
+                               </variable>
+                               <variable name="CPLAYBACKOFFSET">
+                                       <para>Contains the offset in ms into the file where playback
+                                       was at when it stopped. <literal>-1</literal> is end of file.</para>
+                               </variable>
+                               <variable name="CPLAYBACKSTOPKEY">
+                                       <para>If the playback is stopped by the user this variable contains
+                                       the key that was pressed.</para>
+                               </variable>
+                       </variablelist>
+               </description>
+       </application>
+ ***/
 static const char *app = "ControlPlayback";
 
-static const char *synopsis = "Play a file with fast forward and rewind";
-
-static const char *descrip =
-"  ControlPlayback(file[,skipms[,ff[,rew[,stop[,pause[,restart,options]]]]]]]):\n"
-"This application will play back the given filename. By default, the '*' key\n"
-"can be used to rewind, and the '#' key can be used to fast-forward.\n"
-"Parameters:\n"
-"  skipms  - This is number of milliseconds to skip when rewinding or\n"
-"            fast-forwarding.\n"
-"  ff      - Fast-forward when this DTMF digit is received.\n"
-"  rew     - Rewind when this DTMF digit is received.\n"
-"  stop    - Stop playback when this DTMF digit is received.\n"
-"  pause   - Pause playback when this DTMF digit is received.\n"
-"  restart - Restart playback when this DTMF digit is received.\n"
-"Options:\n"
-"  o(#) - Start at # ms from the beginning of the file.\n"
-"This application sets the following channel variables upon completion:\n"
-"  CPLAYBACKSTATUS -  This variable contains the status of the attempt as a text\n"
-"                     string, one of: SUCCESS | USERSTOPPED | ERROR\n"
-"  CPLAYBACKOFFSET -  This contains the offset in ms into the file where\n"
-"                     playback was at when it stopped.  -1 is end of file.\n"
-"  CPLAYBACKSTOPKEY - If the playback is stopped by the user this variable contains\n"
-"                     the key that was pressed.\n";
-
 enum {
        OPT_OFFSET = (1 << 1),
 };
@@ -185,7 +220,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       return ast_register_application(app, controlplayback_exec, synopsis, descrip);
+       return ast_register_application_xml(app, controlplayback_exec);
 }
 
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Control Playback Application");
index f16b4dea69b78d8020d110fc72cacbe642a6d785..cfa445acc649801547c1c20056144e0a53b7f50e 100644 (file)
@@ -52,17 +52,26 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/say.h"
 #include "asterisk/utils.h"
 
+/*** DOCUMENTATION
+       <application name="DAHDIBarge" language="en_US">
+               <synopsis>
+                       Barge in (monitor) DAHDI channel.
+               </synopsis>
+               <syntax>
+                       <parameter name="channel">
+                               <para>Channel to barge.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Barges in on a specified DAHDI <replaceable>channel</replaceable> or prompts
+                       if one is not specified. Returns <literal>-1</literal> when caller user hangs
+                       up and is independent of the state of the channel being monitored.
+                       </para>
+               </description>
+       </application>
+ ***/
 static char *app = "DAHDIBarge";
 
-static char *synopsis = "Barge in (monitor) DAHDI channel";
-
-static char *descrip = 
-"  DAHDIBarge([channel]): Barges in on a specified DAHDI\n"
-"channel or prompts if one is not specified.  Returns\n"
-"-1 when caller user hangs up and is independent of the\n"
-"state of the channel being monitored.";
-
-
 #define CONF_SIZE 160
 
 static int careful_write(int fd, unsigned char *data, int len)
@@ -293,7 +302,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       return ((ast_register_application(app, conf_exec, synopsis, descrip)) ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_SUCCESS);
+       return ((ast_register_application_xml(app, conf_exec)) ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_SUCCESS);
 }
 
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Barge in on DAHDI channel application");
index 1671f8bddf7cf59498d295fa97b5a8a6042a6d8e..879868ea53536ecfdaaf5a25633657870548a0e8 100644 (file)
@@ -52,17 +52,28 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/module.h"
 #include "asterisk/app.h"
 
-static char *app = "DAHDIRAS";
-
-static char *synopsis = "Executes DAHDI ISDN RAS application";
+/*** DOCUMENTATION
+       <application name="DAHDIRAS" language="en_US">
+               <synopsis>
+                       Executes DAHDI ISDN RAS application.
+               </synopsis>
+               <syntax>
+                       <parameter name="args" required="true">
+                               <para>A list of parameters to pass to the pppd daemon,
+                               separeted by <literal>,</literal> characters.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Executes a RAS server using pppd on the given channel.
+                       The channel must be a clear channel (i.e. PRI source) and a DAHDI
+                       channel to be able to use this function (No modem emulation is included).</para>
+                       <para>Your pppd must be patched to be DAHDI aware.</para>
+               </description>
+       </application>
 
-static char *descrip =
-"  DAHDIRAS(args): Executes a RAS server using pppd on the given channel.\n"
-"The channel must be a clear channel (i.e. PRI source) and a DAHDI\n"
-"channel to be able to use this function (No modem emulation is included).\n"
-"Your pppd must be patched to be DAHDI aware. Arguments should be\n"
-"separated by , characters.\n";
+ ***/
 
+static char *app = "DAHDIRAS";
 
 #define PPP_MAX_ARGS   32
 #define PPP_EXEC       "/usr/sbin/pppd"
@@ -218,7 +229,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       return ((ast_register_application(app, dahdiras_exec, synopsis, descrip)) ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_SUCCESS);
+       return ((ast_register_application_xml(app, dahdiras_exec)) ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_SUCCESS);
 }
 
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "DAHDI ISDN Remote Access Server");
index a8a9397257134b2dd229204a1cc86fba446b71a9..8251ffcbffda97c383a1b5e5dca70434ee55918d 100644 (file)
@@ -52,16 +52,24 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/say.h"
 #include "asterisk/options.h"
 
+/*** DOCUMENTATION
+       <application name="DAHDIScan" language="en_US">
+               <synopsis>
+                       Scan DAHDI channels to monitor calls.
+               </synopsis>
+               <syntax>
+                       <parameter name="group">
+                               <para>Limit scanning to a channel <replaceable>group</replaceable> by setting this option.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Allows a call center manager to monitor DAHDI channels in a
+                       convenient way.  Use <literal>#</literal> to select the next channel and use <literal>*</literal> to exit.</para>
+               </description>
+       </application>
+ ***/
 static char *app = "DAHDIScan";
 
-static char *synopsis = "Scan DAHDI channels to monitor calls";
-
-static char *descrip =
-"  DAHDIScan([group]) allows a call center manager to monitor DAHDI channels in\n"
-"a convenient way.  Use '#' to select the next channel and use '*' to exit\n"
-"Limit scanning to a channel GROUP by setting the option group argument.\n";
-
-
 #define CONF_SIZE 160
 
 static struct ast_channel *get_dahdi_channel_locked(int num) {
@@ -363,7 +371,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       return ((ast_register_application(app, conf_exec, synopsis, descrip)) ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_SUCCESS);
+       return ((ast_register_application_xml(app, conf_exec)) ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_SUCCESS);
 }
 
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Scan DAHDI channels application");
index f0fd7463d6e88a833e65a281a2d3032c32018bcb..089523ef41d79778612116b29436931a1ac82c76 100644 (file)
@@ -62,188 +62,396 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/global_datastores.h"
 #include "asterisk/dsp.h"
 
-static char *app = "Dial";
+/*** DOCUMENTATION
+       <application name="Dial" language="en_US">
+               <synopsis>
+                       Attempt to connect to another device or endpoint and bridge the call.
+               </synopsis>
+               <syntax>
+                       <parameter name="Technology/Resource" required="true" argsep="&amp;">
+                               <argument name="Technology/Resource" required="true">
+                                       <para>Specification of the device(s) to dial.  These must be in the format of
+                                       <literal>Technology/Resource</literal>, where <replaceable>Technology</replaceable>
+                                       represents a particular channel driver, and <replaceable>Resource</replaceable>
+                                       represents a resource available to that particular channel driver.</para>
+                               </argument>
+                               <argument name="Technology2/Resource2" required="false" multiple="true">
+                                       <para>Optional extra devices to dial in parallel</para>
+                                       <para>If you need more then one enter them as
+                                       Technology2/Resource2&amp;Technology3/Resourse3&amp;.....</para>
+                               </argument>
+                       </parameter>
+                       <parameter name="timeout" required="false">
+                               <para>Specifies the number of seconds we attempt to dial the specified devices</para>
+                               <para>If not specified, this defaults to 136 years.</para>
+                       </parameter>
+                       <parameter name="options" required="false">
+                          <optionlist>
+                               <option name="A">
+                                       <argument name="x" required="true">
+                                               <para>The file to play to the called party</para>
+                                       </argument>
+                                       <para>Play an announcement to the called party, where <replaceable>x</replaceable> is the prompt to be played</para>
+                               </option>
+                               <option name="C">
+                                       <para>Reset the call detail record (CDR) for this call.</para>
+                               </option>
+                               <option name="c">
+                                       <para>If the Dial() application cancels this call, always set the flag to tell the channel
+                                       driver that the call is answered elsewhere.</para>
+                               </option>
+                               <option name="d">
+                                       <para>Allow the calling user to dial a 1 digit extension while waiting for
+                                       a call to be answered. Exit to that extension if it exists in the
+                                       current context, or the context defined in the <variable>EXITCONTEXT</variable> variable,
+                                       if it exists.</para>
+                               </option>
+                               <option name="D" argsep=":">
+                                       <argument name="called" />
+                                       <argument name="calling" />
+                                       <para>Send the specified DTMF strings <emphasis>after</emphasis> the called
+                                       party has answered, but before the call gets bridged. The 
+                                       <replaceable>called</replaceable> DTMF string is sent to the called party, and the 
+                                       <replaceable>calling</replaceable> DTMF string is sent to the calling party. Both arguments 
+                                       can be used alone.</para>
+                               </option>
+                               <option name="e">
+                                       <para>Execute the <literal>h</literal> extension for peer after the call ends</para>
+                               </option>
+                               <option name="f">
+                                       <para>Force the callerid of the <emphasis>calling</emphasis> channel to be set as the
+                                       extension associated with the channel using a dialplan <literal>hint</literal>.
+                                       For example, some PSTNs do not allow CallerID to be set to anything
+                                       other than the number assigned to the caller.</para>
+                               </option>
+                               <option name="F" argsep="^">
+                                       <argument name="context" required="false" />
+                                       <argument name="exten" required="false" />
+                                       <argument name="priority" required="true" />
+                                       <para>When the caller hangs up, transfer the called party
+                                       to the specified destination and continue execution at that location.</para>
+                               </option>
+                               <option name="g">
+                                       <para>Proceed with dialplan execution at the next priority in the current extension if the
+                                       destination channel hangs up.</para>
+                               </option>
+                               <option name="G" argsep="^">
+                                       <argument name="context" required="false" />
+                                       <argument name="exten" required="false" />
+                                       <argument name="priority" required="true" />
+                                       <para>If the call is answered, transfer the calling party to
+                                       the specified <replaceable>priority</replaceable> and the called party to the specified 
+                                       <replaceable>priority</replaceable> plus one.</para>
+                                       <note>
+                                               <para>You cannot use any additional action post answer options in conjunction with this option.</para>
+                                       </note>
+                               </option>
+                               <option name="h">
+                                       <para>Allow the called party to hang up by sending the <literal>*</literal> DTMF digit.</para>
+                               </option>
+                               <option name="H">
+                                       <para>Allow the calling party to hang up by hitting the <literal>*</literal> DTMF digit.</para>
+                               </option>
+                               <option name="i">
+                                       <para>Asterisk will ignore any forwarding requests it may receive on this dial attempt.</para>
+                               </option>
+                               <option name="k">
+                                       <para>Allow the called party to enable parking of the call by sending
+                                       the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
+                               </option>
+                               <option name="K">
+                                       <para>Allow the calling party to enable parking of the call by sending
+                                       the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
+                               </option>
+                               <option name="L" argsep=":">
+                                       <argument name="x" required="true">
+                                               <para>Maximum call time, in milliseconds</para>
+                                       </argument>
+                                       <argument name="y">
+                                               <para>Warning time, in milliseconds</para>
+                                       </argument>
+                                       <argument name="z">
+                                               <para>Repeat time, in milliseconds</para>
+                                       </argument>
+                                       <para>Limit the call to <replaceable>x</replaceable> milliseconds. Play a warning when <replaceable>y</replaceable> milliseconds are
+                                       left. Repeat the warning every <replaceable>z</replaceable> milliseconds until time expires.</para>
+                                       <para>This option is affected by the following variables:</para>
+                                       <variablelist>
+                                               <variable name="LIMIT_PLAYAUDIO_CALLER">
+                                                       <value name="yes" default="true" />
+                                                       <value name="no" />
+                                                       <para>If set, this variable causes Asterisk to play the prompts to the caller.</para>
+                                               </variable>
+                                               <variable name="LIMIT_PLAYAUDIO_CALLEE">
+                                                       <value name="yes" />
+                                                       <value name="no" default="true"/>
+                                                       <para>If set, this variable causes Asterisk to play the prompts to the callee.</para>
+                                               </variable>
+                                               <variable name="LIMIT_TIMEOUT_FILE">
+                                                       <value name="filename"/>
+                                                       <para>If specified, <replaceable>filename</replaceable> specifies the sound prompt to play when the timeout is reached.
+                                                       If not set, the time remaining will be announced.</para>
+                                               </variable>
+                                               <variable name="LIMIT_CONNECT_FILE">
+                                                       <value name="filename"/>
+                                                       <para>If specified, <replaceable>filename</replaceable> specifies the sound prompt to play when the call begins.
+                                                       If not set, the time remaining will be announced.</para>
+                                               </variable>
+                                               <variable name="LIMIT_WARNING_FILE">
+                                                       <value name="filename"/>
+                                                       <para>If specified, <replaceable>filename</replaceable> specifies the sound prompt to play as
+                                                       a warning when time <replaceable>x</replaceable> is reached. If not set, the time remaining will be announced.</para>
+                                               </variable>
+                                       </variablelist>
+                               </option>
+                               <option name="m">
+                                       <argument name="class" required="false"/>
+                                       <para>Provide hold music to the calling party until a requested
+                                       channel answers. A specific music on hold <replaceable>class</replaceable>
+                                       (as defined in <filename>musiconhold.conf</filename>) can be specified.</para>
+                               </option>
+                               <option name="M" argsep="^">
+                                       <argument name="macro" required="true">
+                                               <para>Name of the macro that should be executed.</para>
+                                       </argument>
+                                       <argument name="arg" multiple="true">
+                                               <para>Macro arguments</para>
+                                       </argument>
+                                       <para>Execute the specified <replaceable>macro</replaceable> for the <emphasis>called</emphasis> channel 
+                                       before connecting to the calling channel. Arguments can be specified to the Macro
+                                       using <literal>^</literal> as a delimiter. The macro can set the variable
+                                       <variable>MACRO_RESULT</variable> to specify the following actions after the macro is
+                                       finished executing:</para>
+                                       <variablelist>
+                                               <variable name="MACRO_RESULT">
+                                                       <para>If set, this action will be taken after the macro finished executing.</para>
+                                                       <value name="ABORT">
+                                                               Hangup both legs of the call
+                                                       </value>
+                                                       <value name="CONGESTION">
+                                                               Behave as if line congestion was encountered
+                                                       </value>
+                                                       <value name="BUSY">
+                                                               Behave as if a busy signal was encountered
+                                                       </value>
+                                                       <value name="CONTINUE">
+                                                               Hangup the called party and allow the calling party to continue dialplan execution at the next priority
+                                                       </value>
+                                                       <!-- TODO: Fix this syntax up, once we've figured out how to specify the GOTO syntax -->
+                                                       <value name="GOTO:&lt;context&gt;^&lt;exten&gt;^&lt;priority&gt;">
+                                                               Transfer the call to the specified destination.
+                                                       </value>
+                                               </variable>
+                                       </variablelist>
+                                       <note>
+                                               <para>You cannot use any additional action post answer options in conjunction
+                                               with this option. Also, pbx services are not run on the peer (called) channel,
+                                               so you will not be able to set timeouts via the TIMEOUT() function in this macro.</para>
+                                       </note>
+                               </option>
+                               <option name="n">
+                                       <para>This option is a modifier for the call screening/privacy mode. (See the 
+                                       <literal>p</literal> and <literal>P</literal> options.) It specifies
+                                       that no introductions are to be saved in the <directory>priv-callerintros</directory>
+                                       directory.</para>
+                               </option>
+                               <option name="N">
+                                       <para>This option is a modifier for the call screening/privacy mode. It specifies
+                                       that if Caller*ID is present, do not screen the call.</para>
+                               </option>
+                               <option name="o">
+                                       <para>Specify that the Caller*ID that was present on the <emphasis>calling</emphasis> channel
+                                       be set as the Caller*ID on the <emphasis>called</emphasis> channel. This was the
+                                       behavior of Asterisk 1.0 and earlier.</para>
+                               </option>
+                               <option name="O">
+                                       <argument name="mode">
+                                               <para>With <replaceable>mode</replaceable> either not specified or set to <literal>1</literal>,
+                                               the originator hanging up will cause the phone to ring back immediately.</para>
+                                               <para>With <replaceable>mode</replaceable> set to <literal>2</literal>, when the operator 
+                                               flashes the trunk, it will ring their phone back.</para>
+                                       </argument>
+                                       <para>Enables <emphasis>operator services</emphasis> mode.  This option only
+                                       works when bridging a DAHDI channel to another DAHDI channel
+                                       only. if specified on non-DAHDI interfaces, it will be ignored.
+                                       When the destination answers (presumably an operator services
+                                       station), the originator no longer has control of their line.
+                                       They may hang up, but the switch will not release their line
+                                       until the destination party (the operator) hangs up.</para>
+                               </option>
+                               <option name="p">
+                                       <para>This option enables screening mode. This is basically Privacy mode
+                                       without memory.</para>
+                               </option>
+                               <option name="P">
+                                       <argument name="x" />
+                                       <para>Enable privacy mode. Use <replaceable>x</replaceable> as the family/key in the AstDB database if
+                                       it is provided. The current extension is used if a database family/key is not specified.</para>
+                               </option>
+                               <option name="r">
+                                       <para>Indicate ringing to the calling party, even if the called party isn't actually ringing. Pass no audio to the calling
+                                       party until the called channel has answered.</para>
+                               </option>
+                               <option name="S">
+                                       <argument name="x" required="true" />
+                                       <para>Hang up the call <replaceable>x</replaceable> seconds <emphasis>after</emphasis> the called party has
+                                       answered the call.</para>
+                               </option>
+                               <option name="t">
+                                       <para>Allow the called party to transfer the calling party by sending the
+                                       DTMF sequence defined in <filename>features.conf</filename>.</para>
+                               </option>
+                               <option name="T">
+                                       <para>Allow the calling party to transfer the called party by sending the
+                                       DTMF sequence defined in <filename>features.conf</filename>.</para>
+                               </option>
+                               <option name="U" argsep="^">
+                                       <argument name="x" required="true">
+                                               <para>Name of the subroutine to execute via Gosub</para>
+                                       </argument>
+                                       <argument name="arg" multiple="true" required="false">
+                                               <para>Arguments for the Gosub routine</para>
+                                       </argument>
+                                       <para>Execute via Gosub the routine <replaceable>x</replaceable> for the <emphasis>called</emphasis> channel before connecting
+                                       to the calling channel. Arguments can be specified to the Gosub
+                                       using <literal>^</literal> as a delimiter. The Gosub routine can set the variable
+                                       <variable>GOSUB_RESULT</variable> to specify the following actions after the Gosub returns.</para>
+                                       <variablelist>
+                                               <variable name="GOSUB_RESULT">
+                                                       <value name="ABORT">
+                                                               Hangup both legs of the call.
+                                                       </value>
+                                                       <value name="CONGESTION">
+                                                               Behave as if line congestion was encountered.
+                                                       </value>
+                                                       <value name="BUSY">
+                                                               Behave as if a busy signal was encountered.
+                                                       </value>
+                                                       <value name="CONTINUE">
+                                                               Hangup the called party and allow the calling party
+                                                               to continue dialplan execution at the next priority.
+                                                       </value>
+                                                       <!-- TODO: Fix this syntax up, once we've figured out how to specify the GOTO syntax -->
+                                                       <value name="GOTO:&lt;context&gt;^&lt;exten&gt;^&lt;priority&gt;">
+                                                               Transfer the call to the specified priority. Optionally, an extension, or
+                                                               extension and priority can be specified.
+                                                       </value>
+                                               </variable>
+                                       </variablelist>
+                                       <note>
+                                               <para>You cannot use any additional action post answer options in conjunction
+                                               with this option. Also, pbx services are not run on the peer (called) channel,
+                                               so you will not be able to set timeouts via the TIMEOUT() function in this routine.</para>
+                                       </note>
+                               </option>
+                               <option name="w">
+                                       <para>Allow the called party to enable recording of the call by sending
+                                       the DTMF sequence defined for one-touch recording in <filename>features.conf</filename>.</para>
+                               </option>
+                               <option name="W">
+                                       <para>Allow the calling party to enable recording of the call by sending
+                                       the DTMF sequence defined for one-touch recording in <filename>features.conf</filename>.</para>
+                               </option>
+                               <option name="x">
+                                       <para>Allow the called party to enable recording of the call by sending
+                                       the DTMF sequence defined for one-touch automixmonitor in <filename>features.conf</filename>.</para>
+                               </option>
+                               <option name="X">
+                                       <para>Allow the calling party to enable recording of the call by sending
+                                       the DTMF sequence defined for one-touch automixmonitor in <filename>features.conf</filename>.</para>
+                               </option>
+                               </optionlist>
+                       </parameter>
+                       <parameter name="URL">
+                               <para>The optional URL will be sent to the called party if the channel driver supports it.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>This application will place calls to one or more specified channels. As soon
+                       as one of the requested channels answers, the originating channel will be
+                       answered, if it has not already been answered. These two channels will then
+                       be active in a bridged call. All other channels that were requested will then
+                       be hung up.</para>
+
+                       <para>Unless there is a timeout specified, the Dial application will wait
+                       indefinitely until one of the called channels answers, the user hangs up, or
+                       if all of the called channels are busy or unavailable. Dialplan executing will
+                       continue if no requested channels can be called, or if the timeout expires.
+                       This application will report normal termination if the originating channel
+                       hangs up, or if the call is bridged and either of the parties in the bridge
+                       ends the call.</para>
+
+                       <para>If the <variable>OUTBOUND_GROUP</variable> variable is set, all peer channels created by this
+                       application will be put into that group (as in Set(GROUP()=...).
+                       If the <variable>OUTBOUND_GROUP_ONCE</variable> variable is set, all peer channels created by this
+                       application will be put into that group (as in Set(GROUP()=...). Unlike OUTBOUND_GROUP,
+                       however, the variable will be unset after use.</para>
+
+                       <para>This application sets the following channel variables:</para>
+                       <variablelist>
+                               <variable name="DIALEDTIME">
+                                       <para>This is the time from dialing a channel until when it is disconnected.</para>
+                               </variable>
+                               <variable name="ANSWEREDTIME">
+                                       <para>This is the amount of time for actual call.</para>
+                               </variable>
+                               <variable name="DIALSTATUS">
+                                       <para>This is the status of the call</para>
+                                       <value name="CHANUNAVAIL" />
+                                       <value name="CONGESTION" />
+                                       <value name="NOANSWER" />
+                                       <value name="BUSY" />
+                                       <value name="ANSWER" />
+                                       <value name="CANCEL" />
+                                       <value name="DONTCALL">
+                                               For the Privacy and Screening Modes.
+                                               Will be set if the called party chooses to send the calling party to the 'Go Away' script.
+                                       </value>
+                                       <value name="TORTURE">
+                                               For the Privacy and Screening Modes.
+                                               Will be set if the called party chooses to send the calling party to the 'torture' script.
+                                       </value>
+                                       <value name="INVALIDARGS" />
+                               </variable>
+                       </variablelist>
+               </description>
+       </application>
+       <application name="RetryDial" language="en_US">
+               <synopsis>
+                       Place a call, retrying on failure allowing an optional exit extension.
+               </synopsis>
+               <syntax>
+                       <parameter name="announce" required="true">
+                               <para>Filename of sound that will be played when no channel can be reached</para>
+                       </parameter>
+                       <parameter name="sleep" required="true">
+                               <para>Number of seconds to wait after a dialattempt failed before a new attempt is made</para>
+                       </parameter>
+                       <parameter name="retries" required="true">
+                               <para>Number of retries</para>
+                               <para>When this is reached flow will continue at the next priority in the dialplan</para>
+                       </parameter>
+                       <parameter name="dialargs" required="true">
+                               <para>Same format as arguments provided to the Dial application</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>This application will attempt to place a call using the normal Dial application.
+                       If no channel can be reached, the <replaceable>announce</replaceable> file will be played.
+                       Then, it will wait <replaceable>sleep</replaceable> number of seconds before retrying the call.
+                       After <replaceable>retries</replaceable> number of attempts, the calling channel will continue at the next priority in the dialplan.
+                       If the <replaceable>retries</replaceable> setting is set to 0, this application will retry endlessly.
+                       While waiting to retry a call, a 1 digit extension may be dialed. If that
+                       extension exists in either the context defined in <variable>EXITCONTEXT</variable> or the current
+                       one, The call will jump to that extension immediately.
+                       The <replaceable>dialargs</replaceable> are specified in the same format that arguments are provided
+                       to the Dial application.</para>
+               </description>
+       </application>
+ ***/
 
-static char *synopsis = "Place a call and connect to the current channel";
-
-static char *descrip =
-"  Dial(Technology/resource[&Tech2/resource2...][,timeout][,options][,URL]):\n"
-"This application will place calls to one or more specified channels. As soon\n"
-"as one of the requested channels answers, the originating channel will be\n"
-"answered, if it has not already been answered. These two channels will then\n"
-"be active in a bridged call. All other channels that were requested will then\n"
-"be hung up.\n"
-"  Unless there is a timeout specified, the Dial application will wait\n"
-"indefinitely until one of the called channels answers, the user hangs up, or\n"
-"if all of the called channels are busy or unavailable. Dialplan executing will\n"
-"continue if no requested channels can be called, or if the timeout expires.\n\n"
-"  This application sets the following channel variables upon completion:\n"
-"    DIALEDTIME   - This is the time from dialing a channel until when it\n"
-"                   is disconnected.\n"
-"    ANSWEREDTIME - This is the amount of time for actual call.\n"
-"    DIALSTATUS   - This is the status of the call:\n"
-"                   CHANUNAVAIL | CONGESTION | NOANSWER | BUSY | ANSWER | CANCEL\n"
-"                   DONTCALL | TORTURE | INVALIDARGS\n"
-"  For the Privacy and Screening Modes, the DIALSTATUS variable will be set to\n"
-"DONTCALL if the called party chooses to send the calling party to the 'Go Away'\n"
-"script. The DIALSTATUS variable will be set to TORTURE if the called party\n"
-"wants to send the caller to the 'torture' script.\n"
-"  This application will report normal termination if the originating channel\n"
-"hangs up, or if the call is bridged and either of the parties in the bridge\n"
-"ends the call.\n"
-"  The optional URL will be sent to the called party if the channel supports it.\n"
-"  If the OUTBOUND_GROUP variable is set, all peer channels created by this\n"
-"application will be put into that group (as in Set(GROUP()=...).\n"
-"  If the OUTBOUND_GROUP_ONCE variable is set, all peer channels created by this\n"
-"application will be put into that group (as in Set(GROUP()=...). Unlike OUTBOUND_GROUP,\n"
-"however, the variable will be unset after use.\n\n"
-"  Options:\n"
-"    A(x) - Play an announcement to the called party, using 'x' as the file.\n"
-"    C    - Reset the CDR for this call.\n"
-"    c    - If DIAL cancels this call, always set the flag to tell the channel\n"
-"           driver that the call is answered elsewhere.\n"
-"    d    - Allow the calling user to dial a 1 digit extension while waiting for\n"
-"           a call to be answered. Exit to that extension if it exists in the\n"
-"           current context, or the context defined in the EXITCONTEXT variable,\n"
-"           if it exists.\n"
-"    D([called][:calling]) - Send the specified DTMF strings *after* the called\n"
-"           party has answered, but before the call gets bridged. The 'called'\n"
-"           DTMF string is sent to the called party, and the 'calling' DTMF\n"
-"           string is sent to the calling party. Both parameters can be used\n"
-"           alone.\n"
-"    e    - execute the 'h' extension for peer after the call ends. This\n"
-"           operation will not be performed if the peer was parked\n"
-"    f    - Force the callerid of the *calling* channel to be set as the\n"
-"           extension associated with the channel using a dialplan 'hint'.\n"
-"           For example, some PSTNs do not allow CallerID to be set to anything\n"
-"           other than the number assigned to the caller.\n"
-"    F(context^exten^pri) - When the caller hangs up, transfer the called party\n"
-"           to the specified context and extension and continue execution.\n"
-"    g    - Proceed with dialplan execution at the current extension if the\n"
-"           destination channel hangs up.\n"
-"    G(context^exten^pri) - If the call is answered, transfer the calling party to\n"
-"           the specified priority and the called party to the specified priority+1.\n"
-"           Optionally, an extension, or extension and context may be specified. \n"
-"           Otherwise, the current extension is used. You cannot use any additional\n"
-"           action post answer options in conjunction with this option.\n"
-"    h    - Allow the called party to hang up by sending the '*' DTMF digit, or\n"
-"           whatever sequence was defined in the featuremap section for\n"
-"           'disconnect' in features.conf\n"
-"    H    - Allow the calling party to hang up by hitting the '*' DTMF digit, or\n"
-"           whatever sequence was defined in the featuremap section for\n"
-"           'disconnect' in features.conf\n"
-"    i    - Asterisk will ignore any forwarding requests it may receive on this\n"
-"           dial attempt.\n"
-"    k    - Allow the called party to enable parking of the call by sending\n"
-"           the DTMF sequence defined for call parking in the featuremap section of features.conf.\n"
-"    K    - Allow the calling party to enable parking of the call by sending\n"
-"           the DTMF sequence defined for call parking in the featuremap section of features.conf.\n"
-"    L(x[:y][:z]) - Limit the call to 'x' ms. Play a warning when 'y' ms are\n"
-"           left. Repeat the warning every 'z' ms. The following special\n"
-"           variables can be used with this option:\n"
-"           * LIMIT_PLAYAUDIO_CALLER   yes|no (default yes)\n"
-"                                      Play sounds to the caller.\n"
-"           * LIMIT_PLAYAUDIO_CALLEE   yes|no\n"
-"                                      Play sounds to the callee.\n"
-"           * LIMIT_TIMEOUT_FILE       File to play when time is up.\n"
-"           * LIMIT_CONNECT_FILE       File to play when call begins.\n"
-"           * LIMIT_WARNING_FILE       File to play as warning if 'y' is defined.\n"
-"                                      The default is to say the time remaining.\n"
-"    m([class]) - Provide hold music to the calling party until a requested\n"
-"           channel answers. A specific MusicOnHold class can be\n"
-"           specified.\n"
-"    M(x[^arg]) - Execute the Macro for the *called* channel before connecting\n"
-"           to the calling channel. Arguments can be specified to the Macro\n"
-"           using '^' as a delimiter. The Macro can set the variable\n"
-"           MACRO_RESULT to specify the following actions after the Macro is\n"
-"           finished executing.\n"
-"           * ABORT        Hangup both legs of the call.\n"
-"           * CONGESTION   Behave as if line congestion was encountered.\n"
-"           * BUSY         Behave as if a busy signal was encountered.\n"
-"           * CONTINUE     Hangup the called party and allow the calling party\n"
-"                          to continue dialplan execution at the next priority.\n"
-"           * GOTO:<context>^<exten>^<priority> - Transfer the call to the\n"
-"                          specified priority. Optionally, an extension, or\n"
-"                          extension and priority can be specified.\n"
-"           You cannot use any additional action post answer options in conjunction\n"
-"           with this option. Also, pbx services are not run on the peer (called) channel,\n"
-"           so you will not be able to set timeouts via the TIMEOUT() function in this macro.\n"
-"    n    - This option is a modifier for the screen/privacy mode. It specifies\n"
-"           that no introductions are to be saved in the priv-callerintros\n"
-"           directory.\n"
-"    N    - This option is a modifier for the screen/privacy mode. It specifies\n"
-"           that if callerID is present, do not screen the call.\n"
-"    o    - Specify that the CallerID that was present on the *calling* channel\n"
-"           be set as the CallerID on the *called* channel. This was the\n"
-"           behavior of Asterisk 1.0 and earlier.\n"
-"    O([x]) - \"Operator Services\" mode (DAHDI channel to DAHDI channel\n"
-"             only, if specified on non-DAHDI interface, it will be ignored).\n"
-"             When the destination answers (presumably an operator services\n"
-"             station), the originator no longer has control of their line.\n"
-"             They may hang up, but the switch will not release their line\n"
-"             until the destination party hangs up (the operator). Specified\n"
-"             without an arg, or with 1 as an arg, the originator hanging up\n"
-"             will cause the phone to ring back immediately. With a 2 specified,\n"
-"             when the \"operator\" flashes the trunk, it will ring their phone\n"
-"             back.\n"
-"    p    - This option enables screening mode. This is basically Privacy mode\n"
-"           without memory.\n"
-"    P([x]) - Enable privacy mode. Use 'x' as the family/key in the database if\n"
-"           it is provided. The current extension is used if a database\n"
-"           family/key is not specified.\n"
-"    r    - Indicate ringing to the calling party. Pass no audio to the calling\n"
-"           party until the called channel has answered.\n"
-"    S(x) - Hang up the call after 'x' seconds *after* the called party has\n"
-"           answered the call.\n"
-"    t    - Allow the called party to transfer the calling party by sending the\n"
-"           DTMF sequence defined in the blindxfer setting in the featuremap section\n"
-"           of features.conf.\n"
-"    T    - Allow the calling party to transfer the called party by sending the\n"
-"           DTMF sequence defined in the blindxfer setting in the featuremap section\n"
-"           of features.conf.\n"
-"    U(x[^arg]) - Execute via Gosub the routine 'x' for the *called* channel before connecting\n"
-"           to the calling channel. Arguments can be specified to the Gosub\n"
-"           using '^' as a delimiter. The Gosub routine can set the variable\n"
-"           GOSUB_RESULT to specify the following actions after the Gosub returns.\n"
-"           * ABORT        Hangup both legs of the call.\n"
-"           * CONGESTION   Behave as if line congestion was encountered.\n"
-"           * BUSY         Behave as if a busy signal was encountered.\n"
-"           * CONTINUE     Hangup the called party and allow the calling party\n"
-"                          to continue dialplan execution at the next priority.\n"
-"           * GOTO:<context>^<exten>^<priority> - Transfer the call to the\n"
-"                          specified priority. Optionally, an extension, or\n"
-"                          extension and priority can be specified.\n"
-"           You cannot use any additional action post answer options in conjunction\n"
-"           with this option. Also, pbx services are not run on the peer (called) channel,\n"
-"           so you will not be able to set timeouts via the TIMEOUT() function in this routine.\n"
-"    w    - Allow the called party to enable recording of the call by sending\n"
-"           the DTMF sequence defined in the automon setting in the featuremap section\n"
-"           of features.conf.\n"
-"    W    - Allow the calling party to enable recording of the call by sending\n"
-"           the DTMF sequence defined in the automon setting in the featuremap section\n"
-"           of features.conf.\n"
-"    x    - Allow the called party to enable recording of the call by sending\n"
-"           the DTMF sequence defined in the automixmon setting in the featuremap section\n"
-"           of features.conf.\n"
-"    X    - Allow the calling party to enable recording of the call by sending\n"
-"           the DTMF sequence defined in the automixmon setting in the featuremap section\n"
-"           of features.conf.\n";
-
-/* RetryDial App by Anthony Minessale II <anthmct@yahoo.com> Jan/2005 */
+static char *app = "Dial";
 static char *rapp = "RetryDial";
-static char *rsynopsis = "Place a call, retrying on failure allowing optional exit extension.";
-static char *rdescrip =
-"  RetryDial(announce,sleep,retries,dialargs): This application will attempt to\n"
-"place a call using the normal Dial application. If no channel can be reached,\n"
-"the 'announce' file will be played. Then, it will wait 'sleep' number of\n"
-"seconds before retrying the call. After 'retries' number of attempts, the\n"
-"calling channel will continue at the next priority in the dialplan. If the\n"
-"'retries' setting is set to 0, this application will retry endlessly.\n"
-"  While waiting to retry a call, a 1 digit extension may be dialed. If that\n"
-"extension exists in either the context defined in ${EXITCONTEXT} or the current\n"
-"one, The call will jump to that extension immediately.\n"
-"  The 'dialargs' are specified in the same format that arguments are provided\n"
-"to the Dial application.\n";
 
 enum {
        OPT_ANNOUNCE =          (1 << 0),
@@ -2187,8 +2395,8 @@ static int load_module(void)
        else
                ast_add_extension2(con, 1, "s", 1, NULL, NULL, "KeepAlive", ast_strdup(""), ast_free_ptr, "app_dial");
 
-       res = ast_register_application(app, dial_exec, synopsis, descrip);
-       res |= ast_register_application(rapp, retrydial_exec, rsynopsis, rdescrip);
+       res = ast_register_application_xml(app, dial_exec);
+       res |= ast_register_application_xml(rapp, retrydial_exec);
 
        return res;
 }
index 86ccad8756fc1d591ba68f36fa90e8c2cdbface9..b780182e3ef447bd28d9c705e735b7c45bfffbf3 100644 (file)
@@ -40,11 +40,22 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/say.h"
 #include "asterisk/app.h"
 
-static char *app = "Dictate";
-static char *synopsis = "Virtual Dictation Machine";
-static char *desc = "  Dictate([<base_dir>[,<filename>]])\n"
-"Start dictation machine using optional base dir for files.\n";
+/*** DOCUMENTATION
+       <application name="Dictate" language="en_US">
+               <synopsis>
+                       Virtual Dictation Machine.
+               </synopsis>
+               <syntax>
+                       <parameter name="base_dir" />
+                       <parameter name="filename" />
+               </syntax>
+               <description>
+                       <para>Start dictation machine using optional <replaceable>base_dir</replaceable> for files.</para>
+               </description>
+       </application>
+ ***/
 
+static char *app = "Dictate";
 
 typedef enum {
        DFLAG_RECORD = (1 << 0),
@@ -332,7 +343,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       return ast_register_application(app, dictate_exec, synopsis, desc);
+       return ast_register_application_xml(app, dictate_exec);
 }
 
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Virtual Dictation Machine");
index 1ead1d77256b812efd01325e5d1a6aa0c7bcba1a..5f88df85db1eb09b3d7d1001dde155cc7540facd 100644 (file)
@@ -43,23 +43,48 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
 #define PICKUPMARK "PICKUPMARK"
 
-static const char *app = "Pickup";
-static const char *synopsis = "Directed Call Pickup";
-static const char *descrip =
-"  Pickup([extension[@context][&extension2@[context]...]]):  This application can\n"
-"pickup any ringing channel that is calling the specified extension.  If no\n"
-"context is specified, the current context will be used. If you use the special\n"
-"string \"PICKUPMARK\" for the context parameter, for example 10@PICKUPMARK,\n"
-"this application tries to find a channel which has defined a ${PICKUPMARK}\n"
-"channel variable with the same value as \"extension\" (in this example, \"10\").\n"
-"When no parameter is specified, the application will pickup a channel matching\n"
-"the pickup group of the active channel.";
+/*** DOCUMENTATION
+       <application name="Pickup" language="en_US">
+               <synopsis>
+                       Directed extension call pickup.
+               </synopsis>
+               <syntax argsep="&amp;">
+                       <parameter name="ext" argsep="@" required="true">
+                               <argument name="extension" required="true"/>
+                               <argument name="context" />
+                       </parameter>
+                       <parameter name="ext2" argsep="@" multiple="true">
+                               <argument name="extension2" required="true"/>
+                               <argument name="context2"/>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>This application can pickup any ringing channel that is calling
+                       the specified <replaceable>extension</replaceable>. If no <replaceable>context</replaceable>
+                       is specified, the current context will be used. If you use the special string <literal>PICKUPMARK</literal>
+                       for the context parameter, for example 10@PICKUPMARK, this application
+                       tries to find a channel which has defined a <variable>PICKUPMARK</variable>
+                       channel variable with the same value as <replaceable>extension</replaceable>
+                       (in this example, <literal>10</literal>). When no parameter is specified, the application
+                       will pickup a channel matching the pickup group of the active channel.</para>
+               </description>
+       </application>
+       <application name="PickupChan" language="en_US">
+               <synopsis>
+                       Pickup a ringing channel.
+               </synopsis>
+               <syntax>
+                       <parameter name="channel" required="true" />
+                       <parameter name="channel2" multiple="true" />
+               </syntax>
+               <description>
+                       <para>This will pickup a specified <replaceable>channel</replaceable> if ringing.</para>
+               </description>
+       </application>
+ ***/
 
+static const char *app = "Pickup";
 static const char *app2 = "PickupChan";
-static const char *synopsis2 = "Pickup a ringing channel";
-static const char *descrip2 =
-"  PickupChan(channel[&channel...]): This application can pickup any ringing channel\n";
-
 /*! \todo This application should return a result code, like PICKUPRESULT */
 
 /* Perform actual pickup between two channels */
@@ -248,8 +273,8 @@ static int load_module(void)
 {
        int res;
 
-       res = ast_register_application(app, pickup_exec, synopsis, descrip);
-       res |= ast_register_application(app2, pickupchan_exec, synopsis2, descrip2);
+       res = ast_register_application_xml(app, pickup_exec);
+       res |= ast_register_application_xml(app2, pickupchan_exec);
 
        return res;
 }
index b2a5741ed13e6ffbdd2b712e5b988a4c879ae3f9..2b0b6776cce9a1215f437217a7fb0c4c16693653 100644 (file)
@@ -42,50 +42,78 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/app.h"
 #include "asterisk/utils.h"
 
-static char *app = "Directory";
+/*** DOCUMENTATION
+       <application name="Directory" language="en_US">
+               <synopsis>
+                       Provide directory of voicemail extensions.
+               </synopsis>
+               <syntax>
+                       <parameter name="vm-context">
+                               <para>This is the context within voicemail.conf to use for the Directory. If not specified and
+                               <literal>searchcontexts=no</literal> in <filename>voicemail.conf</filename>, then <literal>default</literal>
+                               will be assumed.</para>
+                       </parameter>
+                       <parameter name="dial-context" required="false">
+                               <para>This is the dialplan context to use when looking for an
+                               extension that the user has selected, or when jumping to the
+                               <literal>o</literal> or <literal>a</literal> extension.</para>
+                       </parameter>
+                       <parameter name="options" required="false">
+                               <optionlist>
+                                       <option name="e">
+                                               <para>In addition to the name, also read the extension number to the
+                                               caller before presenting dialing options.</para>
+                                       </option>
+                                       <option name="f">
+                                               <para>Allow the caller to enter the first name of a user in the
+                                               directory instead of using the last name.  If specified, the
+                                               optional number argument will be used for the number of
+                                               characters the user should enter.</para>
+                                               <argument name="n" required="true" />
+                                       </option>
+                                       <option name="l">
+                                               <para>Allow the caller to enter the last name of a user in the
+                                               directory.  This is the default.  If specified, the
+                                               optional number argument will be used for the number of
+                                               characters the user should enter.</para>
+                                               <argument name="n" required="true" />
+                                       </option>
+                                       <option name="b">
+                                               <para> Allow the caller to enter either the first or the last name
+                                               of a user in the directory.  If specified, the optional number
+                                               argument will be used for the number of characters the user should enter.</para>
+                                               <argument name="n" required="true" />
+                                       </option>
+                                       <option name="m">
+                                               <para>Instead of reading each name sequentially and asking for
+                                               confirmation, create a menu of up to 8 names.</para>
+                                       </option>
+                                       <option name="p">
+                                               <para>Pause for n milliseconds after the digits are typed.  This is
+                                               helpful for people with cellphones, who are not holding the
+                                               receiver to their ear while entering DTMF.</para>
+                                               <argument name="n" required="true" />
+                                       </option>
+                               </optionlist>
+                               <note><para>Only one of the <replaceable>f</replaceable>, <replaceable>l</replaceable>, or <replaceable>b</replaceable>
+                               options may be specified. <emphasis>If more than one is specified</emphasis>, then Directory will act as 
+                               if <replaceable>b</replaceable> was specified.  The number
+                               of characters for the user to type defaults to <literal>3</literal>.</para></note>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>This application will present the calling channel with a directory of extensions from which they can search
+                       by name. The list of names and corresponding extensions is retrieved from the
+                       voicemail configuration file, <filename>voicemail.conf</filename>.</para>
+                       <para>This application will immediately exit if one of the following DTMF digits are
+                       received and the extension to jump to exists:</para>
+                       <para><literal>0</literal> - Jump to the 'o' extension, if it exists.</para>
+                       <para><literal>*</literal> - Jump to the 'a' extension, if it exists.</para>
+               </description>
+       </application>
 
-static char *synopsis = "Provide directory of voicemail extensions";
-static char *descrip =
-"  Directory([vm-context][,dial-context[,options]]): This application will present\n"
-"the calling channel with a directory of extensions from which they can search\n"
-"by name. The list of names and corresponding extensions is retrieved from the\n"
-"voicemail configuration file, voicemail.conf.\n"
-"  This application will immediately exit if one of the following DTMF digits are\n"
-"received and the extension to jump to exists:\n"
-"    0 - Jump to the 'o' extension, if it exists.\n"
-"    * - Jump to the 'a' extension, if it exists.\n\n"
-"  Parameters:\n"
-"    vm-context   - This is the context within voicemail.conf to use for the\n"
-"                   Directory.  If not specified and searchcontexts=no in\n"
-"                   voicemail.conf, then \"default\" will be assumed.\n"
-"                   Otherwise, in not specified, all contexts will be searched.\n"
-"    dial-context - This is the dialplan context to use when looking for an\n"
-"                   extension that the user has selected, or when jumping to the\n"
-"                   'o' or 'a' extension.\n\n"
-"  Options:\n"
-"    e           In addition to the name, also read the extension number to the\n"
-"              caller before presenting dialing options.\n"
-"    f[(<n>)]    Allow the caller to enter the first name of a user in the\n"
-"              directory instead of using the last name.  If specified, the\n"
-"              optional number argument will be used for the number of\n"
-"              characters the user should enter.\n"
-"    l[(<n>)]    Allow the caller to enter the last name of a user in the\n"
-"              directory.  This is the default.  If specified, the\n"
-"              optional number argument will be used for the number of\n"
-"              characters the user should enter.\n"
-"    b[(<n>)]    Allow the caller to enter either the first or the last name\n"
-"              of a user in the directory.  If specified, the optional number\n"
-"              argument will be used for the number of characters the user\n"
-"              should enter.\n"
-"    m           Instead of reading each name sequentially and asking for\n"
-"              confirmation, create a menu of up to 8 names.\n"
-"    p(<n>)      Pause for n milliseconds after the digits are typed.  This is\n"
-"              helpful for people with cellphones, who are not holding the\n"
-"              receiver to their ear while entering DTMF.\n"
-"\n"
-"    Only one of the f, l, or b options may be specified.  If more than one is\n"
-"    specified, then Directory will act as if 'b' was specified.  The number\n"
-"    of characters for the user to type defaults to 3.\n";
+ ***/
+static char *app = "Directory";
 
 /* For simplicity, I'm keeping the format compatible with the voicemail config,
    but i'm open to suggestions for isolating it */
@@ -809,7 +837,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       return ast_register_application(app, directory_exec, synopsis, descrip);
+       return ast_register_application_xml(app, directory_exec);
 }
 
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Extension Directory");
index 2ed5e15f7b86521230d8f83c91697bc17ee3cb82..515bdce9c09ce12d37c93c0ab1c3a6ab85912c2c 100644 (file)
@@ -45,51 +45,69 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/callerid.h"
 #include "asterisk/stringfields.h"
 
+/*** DOCUMENTATION
+       <application name="DISA" language="en_US">
+               <synopsis>
+                       Direct Inward System Access.
+               </synopsis>
+               <syntax>
+                       <parameter name="passcode|filename" required="true">
+                               <para>If you need to present a DISA dialtone without entering a password,
+                               simply set <replaceable>passcode</replaceable> to <literal>no-password</literal></para>
+                               <para>You may specified a <replaceable>filename</replaceable> instead of a
+                               <replaceable>passcode</replaceable>, this filename must contain individual passcodes</para>
+                       </parameter>
+                       <parameter name="context">
+                               <para>Specifies the dialplan context in which the user-entered extension
+                               will be matched. If no context is specified, the DISA application defaults
+                               to the <literal>disa</literal> context. Presumably a normal system will have a special
+                               context set up for DISA use with some or a lot of restrictions.</para>
+                       </parameter>
+                       <parameter name="cid">
+                               <para>Specifies a new (different) callerid to be used for this call.</para>
+                       </parameter>
+                       <parameter name="mailbox" argsep="@">
+                               <para>Will cause a stutter-dialtone (indication <emphasis>dialrecall</emphasis>)
+                               to be used, if the specified mailbox contains any new messages.</para>
+                               <argument name="mailbox" required="true" />
+                               <argument name="context" required="false" />
+                       </parameter>
+                       <parameter name="options">
+                               <optionlist>
+                                       <option name="n">
+                                               <para>The DISA application will not answer initially.</para>
+                                       </option>
+                                       <option name="p">
+                                               <para>The extension entered will be considered complete when a <literal>#</literal>
+                                               is entered.</para>
+                                       </option>
+                               </optionlist>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>The DISA, Direct Inward System Access, application allows someone from
+                       outside the telephone switch (PBX) to obtain an <emphasis>internal</emphasis> system
+                       dialtone and to place calls from it as if they were placing a call from
+                       within the switch.
+                       DISA plays a dialtone. The user enters their numeric passcode, followed by
+                       the pound sign <literal>#</literal>. If the passcode is correct, the user is then given
+                       system dialtone within <replaceable>context</replaceable> on which a call may be placed.
+                       If the user enters an invalid extension and extension <literal>i</literal> exists in the specified
+                       <replaceable>context</replaceable>, it will be used.
+                       </para>
+                       <para>Be aware that using this may compromise the security of your PBX.</para>
+                       <para>The arguments to this application (in <filename>extensions.conf</filename>) allow either
+                       specification of a single global <replaceable>passcode</replaceable> (that everyone uses), or
+                       individual passcodes contained in a file (<replaceable>filename</replaceable>).</para>
+                       <para>The file that contains the passcodes (if used) allows a complete
+                       specification of all of the same arguments available on the command
+                       line, with the sole exception of the options. The file may contain blank
+                       lines, or comments starting with <literal>#</literal> or <literal>;</literal>.</para>
+               </description>
+       </application>
+ ***/
 static char *app = "DISA";
 
-static char *synopsis = "DISA (Direct Inward System Access)";
-
-static char *descrip =
-"DISA(<numeric passcode>[,<context>[,<cid>[,mailbox[,options]]]]) or\n"
-"DISA(<filename>[,,,,options])\n"
-"The DISA, Direct Inward System Access, application allows someone from \n"
-"outside the telephone switch (PBX) to obtain an \"internal\" system \n"
-"dialtone and to place calls from it as if they were placing a call from \n"
-"within the switch.\n"
-"DISA plays a dialtone. The user enters their numeric passcode, followed by\n"
-"the pound sign (#). If the passcode is correct, the user is then given\n"
-"system dialtone within <context> on which a call may be placed. If the user\n"
-"enters an invalid extension and extension \"i\" exists in the specified\n"
-"context, it will be used.\n"
-"\n"
-"If you need to present a DISA dialtone without entering a password, simply\n"
-"set <passcode> to \"no-password\".\n"
-"\n"
-"Be aware that using this may compromise the security of your PBX.\n"
-"\n"
-"The arguments to this application (in extensions.conf) allow either\n"
-"specification of a single global passcode (that everyone uses), or\n"
-"individual passcodes contained in a file.\n"
-"\n"
-"The file that contains the passcodes (if used) allows a complete\n"
-"specification of all of the same arguments available on the command\n"
-"line, with the sole exception of the options. The file may contain blank\n"
-"lines, or comments starting with \"#\" or \";\".\n"
-"\n"
-"<context> specifies the dialplan context in which the user-entered extension\n"
-"will be matched. If no context is specified, the DISA application defaults\n"
-"the context to \"disa\". Presumably a normal system will have a special\n"
-"context set up for DISA use with some or a lot of restrictions.\n"
-"\n"
-"<cid> specifies a new (different) callerid to be used for this call.\n"
-"\n"
-"<mailbox[@context]> will cause a stutter-dialtone (indication \"dialrecall\")\n"
-"to be used, if the specified mailbox contains any new messages.\n"
-"\n"
-"The following options are available:\n"
-"  n - the DISA application will not answer initially.\n"
-"  p - the extension entered will be considered complete when a '#' is entered.\n";
-
 enum {
        NOANSWER_FLAG = (1 << 0),
        POUND_TO_END_FLAG = (1 << 1),
@@ -363,7 +381,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       return ast_register_application(app, disa_exec, synopsis, descrip) ?
+       return ast_register_application_xml(app, disa_exec) ?
                AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS;
 }
 
index 7742633fd36434fd33c4c8656e6ff812aa963d71..e2300dbeae790f8182d5d2469f7be6f559657857 100644 (file)
@@ -36,15 +36,26 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/module.h"
 #include "asterisk/channel.h"
 
-static char *app = "DumpChan";
-static char *synopsis = "Dump Info About The Calling Channel";
-static char *desc =
-       "   DumpChan([<min_verbose_level>])\n"
-       "Displays information on channel and listing of all channel\n"
-       "variables. If min_verbose_level is specified, output is only\n"
-       "displayed when the verbose level is currently set to that number\n"
-       "or greater. \n";
+/*** DOCUMENTATION
+       <application name="DumpChan" language="en_US">
+               <synopsis>
+                       Dump Info About The Calling Channel.
+               </synopsis>
+               <syntax>
+                       <parameter name="level">
+                               <para>Minimun verbose level</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Displays information on channel and listing of all channel
+                       variables. If <replaceable>level</replaceable> is specified, output is only
+                       displayed when the verbose level is currently set to that number
+                       or greater.</para>
+               </description>
+       </application>
+ ***/
 
+static char *app = "DumpChan";
 
 static int serialize_showchan(struct ast_channel *c, char *buf, size_t size)
 {
@@ -156,7 +167,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       return ast_register_application(app, dumpchan_exec, synopsis, desc);
+       return ast_register_application_xml(app, dumpchan_exec);
 }
 
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Dump Info About The Calling Channel");
index 76c701cd70266b1d289629bad290bd42d37605b3..8b0d21f06dfdc0e965a7d1e8cb0d227d33756072 100644 (file)
@@ -33,15 +33,20 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/module.h"
 #include "asterisk/channel.h"
 
-static char *app = "Echo";
-
-static char *synopsis = "Echo audio, video, or DTMF back to the calling party";
-
-static char *descrip =
-"  Echo(): This application will echo any audio, video, or DTMF frames read from\n"
-"the calling channel back to itself. If the DTMF digit '#' is received, the\n"
-"application will exit.\n";
+/*** DOCUMENTATION
+       <application name="Echo" language="en_US">
+               <synopsis>
+                       Echo audio, video, DTMF back to the calling party
+               </synopsis>
+               <syntax />
+               <description>
+                       <para>Echos back any audio, video or DTMF frames read from the calling 
+                       channel back to itself. Note: If '#' detected application exits</para>
+               </description>
+       </application>
+ ***/
 
+static char *app = "Echo";
 
 static int echo_exec(struct ast_channel *chan, void *data)
 {
@@ -81,7 +86,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       return ast_register_application(app, echo_exec, synopsis, descrip);
+       return ast_register_application_xml(app, echo_exec);
 }
 
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Simple Echo Application");
index 285b8b2f02ddca8053a7a3a887fc79d080480c58..b4a66962e62b2fa0d5e95ad421734b205d706801 100644 (file)
@@ -36,6 +36,80 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/module.h"
 #include "asterisk/app.h"
 
+/*** DOCUMENTATION
+       <application name="Exec" language="en_US">
+               <synopsis>
+                       Executes dialplan application.
+               </synopsis>
+               <syntax>
+                       <parameter name="appname" required="true" hasparams="true">
+                               <para>Application name and arguments of the dialplan application to execute.</para>
+                               <argument name="arguments" required="true" />
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Allows an arbitrary application to be invoked even when not
+                       hardcoded into the dialplan.  If the underlying application
+                       terminates the dialplan, or if the application cannot be found,
+                       Exec will terminate the dialplan.</para>
+                       <para>To invoke external applications, see the application System.
+                       If you would like to catch any error instead, see TryExec.</para>
+               </description>
+       </application>
+       <application name="TryExec" language="en_US">
+               <synopsis>
+                       Executes dialplan application, always returning.
+               </synopsis>
+               <syntax>
+                       <parameter name="appname" required="true" hasparams="true">
+                               <argument name="arguments" required="true" />
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Allows an arbitrary application to be invoked even when not
+                       hardcoded into the dialplan. To invoke external applications
+                       see the application System.  Always returns to the dialplan.
+                       The channel variable TRYSTATUS will be set to one of:
+                       </para>
+                       <variablelist>
+                               <variable name="TRYSTATUS">
+                                       <value name="SUCCESS">
+                                               If the application returned zero.
+                                       </value>
+                                       <value name="FAILED">
+                                               If the application returned non-zero.
+                                       </value>
+                                       <value name="NOAPP">
+                                               If the application was not found or was not specified.
+                                       </value>
+                               </variable>
+                       </variablelist>
+               </description>
+       </application>
+       <application name="ExecIf" language="en_US">
+               <synopsis>
+                       Executes dialplan application, conditionally.
+               </synopsis>
+               <syntax argsep="?">
+                       <parameter name="expression" required="true" />
+                       <parameter name="execapp" required="true" argsep=":">
+                               <argument name="appiftrue" required="true" hasparams="true">
+                                       <argument name="args" required="true" />
+                               </argument>
+                               <argument name="appiffalse" required="false" hasparams="true">
+                                       <argument name="args" required="true" />
+                               </argument>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>If <replaceable>expr</replaceable> is true, execute and return the
+                       result of <replaceable>appiftrue(args)</replaceable>.</para>
+                       <para>If <replaceable>expr</replaceable> is true, but <replaceable>appiftrue</replaceable> is not found,
+                       then the application will return a non-zero value.</para>
+               </description>
+       </application>
+ ***/
+
 /* Maximum length of any variable */
 #define MAXRESULT 1024
 
@@ -52,35 +126,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  */
 
 static char *app_exec = "Exec";
-static char *exec_synopsis = "Executes dialplan application";
-static char *exec_descrip =
-"  Exec(appname(arguments)):\n"
-"Allows an arbitrary application to be invoked even when not\n"
-"hardcoded into the dialplan.  If the underlying application\n"
-"terminates the dialplan, or if the application cannot be found,\n"
-"Exec will terminate the dialplan.\n"
-"  To invoke external applications, see the application System.\n"
-"  If you would like to catch any error instead, see TryExec.\n";
-
 static char *app_tryexec = "TryExec";
-static char *tryexec_synopsis = "Executes dialplan application, always returning";
-static char *tryexec_descrip =
-"  TryExec(appname(arguments)):\n"
-"Allows an arbitrary application to be invoked even when not\n"
-"hardcoded into the dialplan. To invoke external applications\n"
-"see the application System.  Always returns to the dialplan.\n"
-"The channel variable TRYSTATUS will be set to one of:\n"
-"    SUCCESS   if the application returned zero\n"
-"    FAILED    if the application returned non-zero\n"
-"    NOAPP     if the application was not found or was not specified\n";
-
 static char *app_execif = "ExecIf";
-static char *execif_synopsis = "Executes dialplan application, conditionally";
-static char *execif_descrip =
-"  ExecIF (<expr>?<appiftrue>(<args>)[:<appiffalse>(<args>)])\n"
-"If <expr> is true, execute and return the result of <appiftrue>(<args>).\n"
-"If <expr> is true, but <appiftrue> is not found, then the application\n"
-"will return a non-zero value.\n";
 
 static int exec_exec(struct ast_channel *chan, void *data)
 {
@@ -237,9 +284,9 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       int res = ast_register_application(app_exec, exec_exec, exec_synopsis, exec_descrip);
-       res |= ast_register_application(app_tryexec, tryexec_exec, tryexec_synopsis, tryexec_descrip);
-       res |= ast_register_application(app_execif, execif_exec, execif_synopsis, execif_descrip);
+       int res = ast_register_application_xml(app_exec, exec_exec);
+       res |= ast_register_application_xml(app_tryexec, tryexec_exec);
+       res |= ast_register_application_xml(app_execif, execif_exec);
        return res;
 }
 
index 9d72f3fe153793133e5a6189863bbd30715f53e9..41d76b4bff027cecaf2903ab651297ba78bb3cb5 100644 (file)
@@ -41,60 +41,105 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/module.h"
 #include "asterisk/manager.h"
 
-static char *app_sndfax_name = "SendFAX";
-static char *app_sndfax_synopsis = "Send a FAX";
-static char *app_sndfax_desc = 
-"  SendFAX(filename[|options]):\n"
-"Send a given TIFF file to the channel as a FAX.\n"
-"The option string may contain zero or more of the following characters:\n"
-"     'a' - makes the application behave as an answering machine\n"
-"           The default behaviour is to behave as a calling machine.\n"
-"\n"
-"This application uses following variables:\n"
-"     LOCALSTATIONID to identify itself to the remote end.\n"
-"     LOCALHEADERINFO to generate a header line on each page.\n"
-"\n"
-"This application sets the following channel variables upon completion:\n"
-"     FAXSTATUS       - status of operation:\n"
-"                           SUCCESS | FAILED\n"
-"     FAXERROR        - Error when FAILED\n"
-"     FAXMODE         - Mode used:\n"
-"                           audio | T38\n"
-"     REMOTESTATIONID - CSID of the remote side.\n"
-"     FAXPAGES        - number of pages sent.\n"
-"     FAXBITRATE      - transmition rate.\n"
-"     FAXRESOLUTION   - resolution.\n"
-"\n"
-"Returns -1 in case of user hang up or any channel error.\n"
-"Returns 0 on success.\n";
+/*** DOCUMENTATION
+       <application name="SendFAX" language="en_US">
+               <synopsis>
+                       Send a Fax
+               </synopsis>
+               <syntax>
+                       <parameter name="filename" required="true">
+                               <para>Filename of TIFF file to fax</para>
+                       </parameter>
+                       <parameter name="a" required="false">
+                               <para>Makes the application behave as the answering machine</para>
+                               <para>(Default behavior is as calling machine)</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Send a given TIFF file to the channel as a FAX.</para>
+                       <para>This application sets the following channel variables:</para>
+                       <variablelist>
+                               <variable name="LOCALSTATIONID">
+                                       <para>To identify itself to the remote end</para>
+                               </variable>
+                               <variable name="LOCALHEADERINFO">
+                                       <para>To generate a header line on each page</para>
+                               </variable>
+                               <variable name="FAXSTATUS">
+                                       <value name="SUCCESS"/>
+                                       <value name="FAILED"/>
+                               </variable>
+                               <variable name="FAXERROR">
+                                       <para>Cause of failure</para>
+                               </variable>
+                               <variable name="REMOTESTATIONID">
+                                       <para>The CSID of the remote side</para>
+                               </variable>
+                               <variable name="FAXPAGES">
+                                       <para>Number of pages sent</para>
+                               </variable>
+                               <variable name="FAXBITRATE">
+                                       <para>Transmission rate</para>
+                               </variable>
+                               <variable name="FAXRESOLUTION">
+                                       <para>Resolution of sent fax</para>
+                               </variable>
+                       </variablelist>
+               </description>
+       </application>
+       <application name="ReceiveFAX" language="en_US">
+               <synopsis>
+                       Receive a Fax
+               </synopsis>
+               <syntax>
+                       <parameter name="filename" required="true">
+                               <para>Filename of TIFF file save incoming fax</para>
+                       </parameter>
+                       <parameter name="c" required="false">
+                               <para>Makes the application behave as the calling machine</para> 
+                               <para>(Default behavior is as answering machine)</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Receives a FAX from the channel into the given filename 
+                       overwriting the file if it already exists.</para>
+                       <para>File created will be in TIFF format.</para>
+
+                       <para>This application sets the following channel variables:</para>
+                       <variablelist>
+                               <variable name="LOCALSTATIONID">
+                                       <para>To identify itself to the remote end</para>
+                               </variable>
+                               <variable name="LOCALHEADERINFO">
+                                       <para>To generate a header line on each page</para>
+                               </variable>
+                               <variable name="FAXSTATUS">
+                                       <value name="SUCCESS"/>
+                                       <value name="FAILED"/>
+                               </variable>
+                               <variable name="FAXERROR">
+                                       <para>Cause of failure</para>
+                               </variable>
+                               <variable name="REMOTESTATIONID">
+                                       <para>The CSID of the remote side</para>
+                               </variable>
+                               <variable name="FAXPAGES">
+                                       <para>Number of pages sent</para>
+                               </variable>
+                               <variable name="FAXBITRATE">
+                                       <para>Transmission rate</para>
+                               </variable>
+                               <variable name="FAXRESOLUTION">
+                                       <para>Resolution of sent fax</para>
+                               </variable>
+                       </variablelist>
+               </description>
+       </application>
+
+ ***/
 
+static char *app_sndfax_name = "SendFAX";
 static char *app_rcvfax_name = "ReceiveFAX";
-static char *app_rcvfax_synopsis = "Receive a FAX";
-static char *app_rcvfax_desc = 
-"  ReceiveFAX(filename[|options]):\n"
-"Receives a fax from the channel into the given filename overwriting\n"
-"the file if it already exists. File created will have TIFF format.\n"
-"The option string may contain zero or more of the following characters:\n"
-"     'c' -- makes the application behave as a calling machine\n"
-"            The default behaviour is to behave as an answering machine.\n"
-"\n"
-"This application uses following variables:\n"
-"     LOCALSTATIONID to identify itself to the remote end.\n"
-"     LOCALHEADERINFO to generate a header line on each page.\n"
-"\n"
-"This application sets the following channel variables upon completion:\n"
-"     FAXSTATUS       - status of operation:\n"
-"                           SUCCESS | FAILED\n"
-"     FAXERROR        - Error when FAILED\n"
-"     FAXMODE         - Mode used:\n"
-"                           audio | T38\n"
-"     REMOTESTATIONID - CSID of the remote side.\n"
-"     FAXPAGES        - number of pages sent.\n"
-"     FAXBITRATE      - transmition rate.\n"
-"     FAXRESOLUTION   - resolution.\n"
-"\n"
-"Returns -1 in case of user hang up or any channel error.\n"
-"Returns 0 on success.\n";
 
 #define MAX_SAMPLES 240
 
@@ -753,8 +798,8 @@ static int load_module(void)
 {
        int res ;
 
-       res = ast_register_application(app_sndfax_name, sndfax_exec, app_sndfax_synopsis, app_sndfax_desc);
-       res |= ast_register_application(app_rcvfax_name, rcvfax_exec, app_rcvfax_synopsis, app_rcvfax_desc);
+       res = ast_register_application_xml(app_sndfax_name, sndfax_exec);
+       res |= ast_register_application_xml(app_rcvfax_name, rcvfax_exec);
 
        /* The default SPAN message handler prints to stderr. It is something we do not want */
        span_set_message_handler(NULL);
index 4a929a3e51d4e30f66fd237c68f90d5d7aca4f12..82f1bddc598761b3931f6042ed425b431d2b4b10 100644 (file)
@@ -53,15 +53,24 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #define MAXLEN 180
 #define MAXFESTLEN 2048
 
-static char *app = "Festival";
-
-static char *synopsis = "Say text to the user";
-
-static char *descrip = 
-"  Festival(text[,intkeys]):  Connect to Festival, send the argument, get back the waveform,\n"
-"play it to the user, allowing any given interrupt keys to immediately terminate and return\n"
-"the value, or 'any' to allow any number back (useful in dialplan)\n";
+/*** DOCUMENTATION
+       <application name="Festival" language="en_US">
+               <synopsis>
+                       Say text to the user.
+               </synopsis>
+               <syntax>
+                       <parameter name="text" required="true" />
+                       <parameter name="intkeys" />
+               </syntax>
+               <description>
+                       <para>Connect to Festival, send the argument, get back the waveform, play it to the user,
+                       allowing any given interrupt keys to immediately terminate and return the value, or
+                       <literal>any</literal> to allow any number back (useful in dialplan).</para>
+               </description>
+       </application>
+ ***/
 
+static char *app = "Festival";
 
 static char *socket_receive_file_to_buff(int fd, int *size)
 {
@@ -526,7 +535,7 @@ static int load_module(void)
                return AST_MODULE_LOAD_DECLINE;
        }
        ast_config_destroy(cfg);
-       return ast_register_application(app, festival_exec, synopsis, descrip);
+       return ast_register_application_xml(app, festival_exec);
 }
 
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Simple Festival Interface");
index 6ff051899d087dc43b5c86bd4ff69f61dd8c9b40..9c100924283fd073a433bcac861cce6509823523 100644 (file)
@@ -36,15 +36,20 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/module.h"
 #include "asterisk/adsi.h"
 
+/*** DOCUMENTATION
+       <application name="GetCPEID" language="en_US">
+               <synopsis>
+                       Get ADSI CPE ID.
+               </synopsis>
+               <syntax />
+               <description>
+                       <para>Obtains and displays ADSI CPE ID and other information in order
+                       to properly setup <filename>dahdi.conf</filename> for on-hook operations.</para>
+               </description>
+       </application>
+ ***/
 static char *app = "GetCPEID";
 
-static char *synopsis = "Get ADSI CPE ID";
-
-static char *descrip =
-"  GetCPEID(): Obtains and displays ADSI CPE ID and other information in order\n"
-"to properly setup dahdi.conf for on-hook operations.\n";
-
-
 static int cpeid_setstatus(struct ast_channel *chan, char *stuff[], int voice)
 {
        int justify[5] = { ADSI_JUST_CENT, ADSI_JUST_LEFT, ADSI_JUST_LEFT, ADSI_JUST_LEFT };
@@ -124,7 +129,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       return ast_register_application(app, cpeid_exec, synopsis, descrip);
+       return ast_register_application_xml(app, cpeid_exec);
 }
 
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Get ADSI CPE ID");
index 1da17369be3a27bc478935615c76c8c2cdd6aeb7..4126ad7e95c7146a3d50fc2803d567a527475f50 100644 (file)
@@ -45,21 +45,30 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/translate.h"
 #include "asterisk/app.h"
 
+/*** DOCUMENTATION
+       <application name="ICES" language="en_US">
+               <synopsis>
+                       Encode and stream using 'ices'.
+               </synopsis>
+               <syntax>
+                       <parameter name="config" required="true">
+                               <para>ICES configuration file.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Streams to an icecast server using ices (available separately).
+                       A configuration file must be supplied for ices (see contrib/asterisk-ices.xml).</para>
+                       <note><para>ICES version 2 cient and server required.</para></note>
+               </description>
+       </application>
+
+ ***/
+
 #define path_BIN "/usr/bin/"
 #define path_LOCAL "/usr/local/bin/"
 
 static char *app = "ICES";
 
-static char *synopsis = "Encode and stream using 'ices'";
-
-static char *descrip = 
-"  ICES(config.xml) Streams to an icecast server using ices\n"
-"(available separately).  A configuration file must be supplied\n"
-"for ices (see contrib/asterisk-ices.xml). \n"
-"\n"
-"- ICES version 2 cient and server required.\n";
-
-
 static int icesencode(char *filename, int fd)
 {
        int res;
@@ -199,7 +208,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       return ast_register_application(app, ices_exec, synopsis, descrip);
+       return ast_register_application_xml(app, ices_exec);
 }
 
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Encode and Stream via icecast and ices");
index ac44495e30b13c807bc1367e86a679077fd3e6fe..e74397c0dedbd443400399be9a717bb0357afd6e 100644 (file)
@@ -35,16 +35,35 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
 static char *app = "SendImage";
 
-static char *synopsis = "Send an image file";
-
-static char *descrip = 
-"  SendImage(filename): Sends an image on a channel.\n"
-"Result of transmission will be stored in SENDIMAGESTATUS\n"
-"channel variable:\n"
-"    SUCCESS      Transmission succeeded\n"
-"    FAILURE      Transmission failed\n"
-"    UNSUPPORTED  Image transmission not supported by channel\n";
-
+/*** DOCUMENTATION
+       <application name="SendImage" language="en_US">
+               <synopsis>
+                       Sends an image file.
+               </synopsis>
+               <syntax>
+                       <parameter name="filename" required="true">
+                               <para>Path of the filename (image) to send.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Send an image file on a channel supporting it.</para>
+                       <para>Result of transmission will be stored in <variable>SENDIMAGESTATUS</variable></para>
+                       <variablelist>
+                               <variable name="SENDIMAGESTATUS">
+                                       <value name="SUCCESS">
+                                               Transmission succeeded.
+                                       </value>
+                                       <value name="FAILURE">
+                                               Transmission failed.
+                                       </value>
+                                       <value name="UNSUPPORTED">
+                                               Image transmission not supported by channel.
+                                       </value>
+                               </variable>
+                       </variablelist>
+               </description>
+       </application>
+ ***/
 
 static int sendimage_exec(struct ast_channel *chan, void *data)
 {
@@ -76,7 +95,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       return ast_register_application(app, sendimage_exec, synopsis, descrip);
+       return ast_register_application_xml(app, sendimage_exec);
 }
 
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Image Transmission Application");
index 4da4c9f8b19983d033fba0c47a149a23342f4614..14546b3c435301e3ffda8099c1875091a920161e 100644 (file)
@@ -73,18 +73,46 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 "                running.\n" \
 "    c(<name>) - By default, Asterisk will use the channel name for the jack client\n" \
 "                name.  Use this option to specify a custom client name.\n"
-
+/*** DOCUMENTATION
+       <application name="JACK" language="en_US">
+               <synopsis>
+                       Jack Audio Connection Kit
+               </synopsis>
+               <syntax>
+                       <parameter name="options" required="false">
+                               <optionlist>
+                                       <option name="s">
+                                               <argument name="name" required="true">
+                                                       <para>Connect to the specified jack server name</para>
+                                               </argument>
+                                       </option>
+                                       <option name="i">
+                                               <argument name="name" required="true">
+                                                       <para>Connect the output port that gets created to the specified jack input port</para>
+                                               </argument>
+                                       </option>
+                                       <option name="o">
+                                               <argument name="name" required="true">
+                                                       <para>Connect the input port that gets created to the specified jack output port</para>
+                                               </argument>
+                                       </option>
+                                       <option name="c">
+                                               <argument name="name" required="true">
+                                                       <para>By default, Asterisk will use the channel name for the jack client name.</para>
+                                                       <para>Use this option to specify a custom client name.</para>
+                                               </argument>
+                                       </option>
+                               </optionlist>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>When executing this application, two jack ports will be created; 
+                       one input and one output. Other applications can be hooked up to 
+                       these ports to access audio coming from, or being send to the channel.</para>
+               </description>
+       </application>
+ ***/
 static char *jack_app = "JACK";
-static char *jack_synopsis = 
-"JACK (Jack Audio Connection Kit) Application";
-static char *jack_desc = 
-"JACK([options])\n"
-"  When this application is executed, two jack ports will be created; one input\n"
-"and one output.  Other applications can be hooked up to these ports to access\n"
-"the audio coming from, or being sent to the channel.\n"
-"  Valid options:\n"
-COMMON_OPTIONS
-"";
 
 struct jack_data {
        AST_DECLARE_STRING_FIELDS(
@@ -982,7 +1010,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       if (ast_register_application(jack_app, jack_exec, jack_synopsis, jack_desc)) {
+       if (ast_register_application_xml(jack_app, jack_exec)) {
                return AST_MODULE_LOAD_DECLINE;
        }
 
index 89063096cde935d0743e3a949ee0223e32865d73..4c6a9ea4c865e19db253a0c9a884a845b8ac2a58 100644 (file)
@@ -37,16 +37,29 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/channel.h"
 #include "asterisk/pbx.h"
 
-static char *app = "Milliwatt";
-
-static char *synopsis = "Generate a Constant 1004Hz tone at 0dbm (mu-law)";
+/*** DOCUMENTATION
+       <application name="Milliwatt" language="en_US">
+               <synopsis>
+                       Generate a Constant 1004Hz tone at 0dbm (mu-law).
+               </synopsis>
+               <syntax>
+                       <parameter name="options">
+                               <optionlist>
+                                       <option name="o">
+                                               <para>Generate the tone at 1000Hz like previous version.</para>
+                                       </option>
+                               </optionlist>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Previous versions of this application generated the tone at 1000Hz.  If for
+                       some reason you would prefer that behavior, supply the <literal>o</literal> option to get the
+                       old behavior.</para>
+               </description>
+       </application>
+ ***/
 
-static char *descrip = 
-"   Milliwatt([options]): Generate a Constant 1004Hz tone at 0dbm.\n"
-"Previous versions of this application generated the tone at 1000Hz.  If for\n"
-"some reason you would prefer that behavior, supply the 'o' option to get the\n"
-"old behavior.\n"
-"";
+static char *app = "Milliwatt";
 
 static char digital_milliwatt[] = {0x1e,0x0b,0x0b,0x1e,0x9e,0x8b,0x8b,0x9e} ;
 
@@ -161,7 +174,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       return ast_register_application(app, milliwatt_exec, synopsis, descrip);
+       return ast_register_application_xml(app, milliwatt_exec);
 }
 
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Digital Milliwatt (mu-law) Test Application");
index 0adaa62fe0249f4da7bc86144ab5780ff15c3a0a..2955455d370bfd49b4aa9232d2a4173d9aff7dd3 100644 (file)
@@ -46,38 +46,78 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/app.h"
 #include "asterisk/channel.h"
 
+/*** DOCUMENTATION
+       <application name="MixMonitor" language="en_US">
+               <synopsis>
+                       Record a call and mix the audio during the recording.
+               </synopsis>
+               <syntax>
+                       <parameter name="file" required="true" argsep=".">
+                               <argument name="filename" required="true">
+                                       <para>If <replaceable>filename</replaceable> is an absolute path, uses that path, otherwise
+                                       creates the file in the configured monitoring directory from <filename>asterisk.conf.</filename></para>
+                               </argument>
+                               <argument name="extension" required="true" />
+                       </parameter>
+                       <parameter name="options">
+                               <optionlist>
+                                       <option name="a">
+                                               <para>Append to the file instead of overwriting it.</para>
+                                       </option>
+                                       <option name="b">
+                                               <para>Only save audio to the file while the channel is bridged.</para>
+                                               <note><para>Does not include conferences or sounds played to each bridged party</para></note>
+                                       </option>
+                                       <option name="v">
+                                               <para>Adjust the <emphasis>heard</emphasis> volume by a factor of <replaceable>x</replaceable>
+                                               (range <literal>-4</literal> to <literal>4</literal>)</para>
+                                               <argument name="x" required="true" />
+                                       </option>
+                                       <option name="V">
+                                               <para>Adjust the <emphasis>spoken</emphasis> volume by a factor
+                                               of <replaceable>x</replaceable> (range <literal>-4</literal> to <literal>4</literal>)</para>
+                                               <argument name="x" required="true" />
+                                       </option>
+                                       <option name="W">
+                                               <para>Adjust both, <emphasis>heard and spoken</emphasis> volumes by a factor
+                                               of <replaceable>x</replaceable> (range <literal>-4</literal> to <literal>4</literal>)</para>
+                                               <argument name="x" required="true" />
+                                       </option>
+                               </optionlist>
+                       </parameter>
+                       <parameter name="command">
+                               <para>Will be executed when the recording is over.</para>
+                               <para>Any strings matching <literal>^{X}</literal> will be unescaped to <variable>X</variable>.</para>
+                               <para>All variables will be evaluated at the time MixMonitor is called.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Records the audio on the current channel to the specified file.</para>
+                       <variablelist>
+                               <variable name="MIXMONITOR_FILENAME">
+                                       <para>Will contain the filename used to record.</para>
+                               </variable>
+                       </variablelist> 
+               </description>
+       </application>
+       <application name="StopMixMonitor" language="en_US">
+               <synopsis>
+                       Stop recording a call through MixMonitor.
+               </synopsis>
+               <syntax />
+               <description>
+                       <para>Stops the audio recording that was started with a call to <literal>MixMonitor()</literal>
+                       on the current channel.</para>
+               </description>
+       </application>
+               
+ ***/
+
 #define get_volfactor(x) x ? ((x > 0) ? (1 << x) : ((1 << abs(x)) * -1)) : 0
 
 static const char *app = "MixMonitor";
-static const char *synopsis = "Record a call and mix the audio during the recording";
-static const char *desc = ""
-"  MixMonitor(<file>.<ext>[,<options>[,<command>]]):\n"
-"Records the audio on the current channel to the specified file.\n"
-"If the filename is an absolute path, uses that path, otherwise\n"
-"creates the file in the configured monitoring directory from\n"
-"asterisk.conf.\n\n"
-"Valid options:\n"
-" a      - Append to the file instead of overwriting it.\n"
-" b      - Only save audio to the file while the channel is bridged.\n"
-"          Note: Does not include conferences or sounds played to each bridged\n"
-"                party.\n"
-" v(<x>) - Adjust the heard volume by a factor of <x> (range -4 to 4)\n"       
-" V(<x>) - Adjust the spoken volume by a factor of <x> (range -4 to 4)\n"      
-" W(<x>) - Adjust the both heard and spoken volumes by a factor of <x>\n"
-"         (range -4 to 4)\n\n" 
-"<command> will be executed when the recording is over\n"
-"Any strings matching ^{X} will be unescaped to ${X}.\n"
-"All variables will be evaluated at the time MixMonitor is called.\n"
-"The variable MIXMONITOR_FILENAME will contain the filename used to record.\n"
-"";
 
 static const char *stop_app = "StopMixMonitor";
-static const char *stop_synopsis = "Stop recording a call through MixMonitor";
-static const char *stop_desc = ""
-"  StopMixMonitor():\n"
-"Stops the audio recording that was started with a call to MixMonitor()\n"
-"on the current channel.\n"
-"";
 
 struct module_symbols *me;
 
@@ -415,8 +455,8 @@ static int load_module(void)
        int res;
 
        ast_cli_register_multiple(cli_mixmonitor, sizeof(cli_mixmonitor) / sizeof(struct ast_cli_entry));
-       res = ast_register_application(app, mixmonitor_exec, synopsis, desc);
-       res |= ast_register_application(stop_app, stop_mixmonitor_exec, stop_synopsis, stop_desc);
+       res = ast_register_application_xml(app, mixmonitor_exec);
+       res |= ast_register_application_xml(stop_app, stop_mixmonitor_exec);
 
        return res;
 }
index 455ee04c1b8b535d4301b796b27319ce0c7d3240..f9005296a1300694c09f1b257790056454484276 100644 (file)
@@ -34,18 +34,33 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/module.h"
 #include "asterisk/indications.h"
 
+/*** DOCUMENTATION
+       <application name="Morsecode" language="en_US">
+               <synopsis>
+                       Plays morse code
+               </synopsis>
+               <syntax>
+                       <parameter name="string" required="true">
+                               <para>String to playback as morse code to channel</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Plays the Morse code equivalent of the passed string.</para>
+
+                       <para>This application uses the following variables:</para>
+                       <variablelist>
+                               <variable name="MORSEDITLEN">
+                                       <para>Use this value in (ms) for length of dit</para>
+                               </variable>
+                               <variable name="MORSETONE">
+                                       <para>The pitch of the tone in (Hz), default is 800</para>
+                               </variable>
+                       </variablelist>
+               </description>
+       </application>
+ ***/  
 static char *app_morsecode = "Morsecode";
 
-static char *morsecode_synopsis = "Plays morse code";
-
-static char *morsecode_descrip =
-"  Morsecode(<string>):\n"
-"Plays the Morse code equivalent of the passed string.  If the variable\n"
-"MORSEDITLEN is set, it will use that value for the length (in ms) of the dit\n"
-"(defaults to 80).  Additionally, if MORSETONE is set, it will use that tone\n"
-"(in Hz).  The tone default is 800.\n";
-
-
 static char *morsecode[] = {
        "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /*  0-15 */
        "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /* 16-31 */
@@ -159,7 +174,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       return ast_register_application(app_morsecode, morsecode_exec, morsecode_synopsis, morsecode_descrip);
+       return ast_register_application_xml(app_morsecode, morsecode_exec);
 }
 
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Morse code");
index 23db94fbc58d00d6231bd86336b626f973d5756b..688be6a00015e8150d1039f8eb00994e5bfe75a3 100644 (file)
@@ -44,16 +44,26 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #define LOCAL_MPG_123 "/usr/local/bin/mpg123"
 #define MPG_123 "/usr/bin/mpg123"
 
+/*** DOCUMENTATION
+       <application name="MP3Player" language="en_US">
+               <synopsis>
+                       Play an MP3 file or stream.
+               </synopsis>
+               <syntax>
+                       <parameter name="Location" required="true">
+                               <para>Location of the file to be played.
+                               (argument passed to mpg123)</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Executes mpg123 to play the given location, which typically would be a filename or a URL.
+                       User can exit by pressing any key on the dialpad, or by hanging up.</para>
+               </description>
+       </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. User can exit by pressing\n"
-"any key on the dialpad, or by hanging up."; 
-
-
 static int mp3play(char *filename, int fd)
 {
        int res;
@@ -221,7 +231,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       return ast_register_application(app, mp3_exec, synopsis, descrip);
+       return ast_register_application_xml(app, mp3_exec);
 }
 
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Silly MP3 Application");
index 5bc920f50fe967f086ae322de1a3285edf2b7deb..dd071ef0e649078247e567dc9d00a49e79e0fdc4 100644 (file)
@@ -43,6 +43,19 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/translate.h"
 #include "asterisk/app.h"
 
+/*** DOCUMENTATION
+       <application name="NBScat" language="en_US">
+               <synopsis>
+                       Play an NBS local stream.
+               </synopsis>
+               <syntax />
+               <description>
+                       <para>Executes nbscat to listen to the local NBS stream.
+                       User can exit by pressing any key.</para>
+               </description>
+       </application>
+ ***/
+
 #define LOCAL_NBSCAT "/usr/local/bin/nbscat8k"
 #define NBSCAT "/usr/bin/nbscat8k"
 
@@ -52,13 +65,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
 static char *app = "NBScat";
 
-static char *synopsis = "Play an NBS local stream";
-
-static char *descrip = 
-"  NBScat(): Executes nbscat to listen to the local NBS stream.\n"
-"User can exit by pressing any key.\n";
-
-
 static int NBScatplay(int fd)
 {
        int res;
@@ -204,7 +210,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       return ast_register_application(app, NBScat_exec, synopsis, descrip);
+       return ast_register_application_xml(app, NBScat_exec);
 }
 
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Silly NBS Stream Application");
index 33ff1b489e9efd15a6515c906bed310580e7548b..7aacbd9d6601612a902dc5fed8ec15f7d0944612 100644 (file)
@@ -44,24 +44,57 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/devicestate.h"
 #include "asterisk/dial.h"
 
+/*** DOCUMENTATION
+       <application name="Page" language="en_US">
+               <synopsis>
+                       Page series of phones
+               </synopsis>
+               <syntax>
+                       <parameter name="Technology/Resource" required="true" argsep="&amp;">
+                               <argument name="Technology/Resource" required="true">
+                                       <para>Specification of the device(s) to dial. These must be in the format of
+                                       <literal>Technology/Resource</literal>, where <replaceable>Technology</replaceable>
+                                       represents a particular channel driver, and <replaceable>Resource</replaceable> represents a resource
+                                       available to that particular channel driver.</para>
+                               </argument>
+                               <argument name="Technology2/Resource2" multiple="true">
+                                       <para>Optional extra devices to dial inparallel</para>
+                                       <para>If you need more then one enter them as Technology2/Resource2&amp;
+                                       Technology3/Resourse3&amp;.....</para>
+                               </argument>
+                       </parameter>
+                       <parameter name="options">
+                               <optionlist>
+                                       <option name="d">
+                                               <para>Full duplex audio</para>
+                                       </option>
+                                       <option name="q">
+                                               <para>Quiet, do not play beep to caller</para>
+                                       </option>
+                                       <option name="r">
+                                               <para>Record the page into a file (meetme option <literal>r</literal>)</para>
+                                       </option>
+                                       <option name="s">
+                                               <para>Only dial channel if devicestate says its <literal>notinuse</literal></para>
+                                       </option>
+                               </optionlist>
+                       </parameter>
+                       <parameter name="timeout">
+                               <para>Specify the length of time that the system will attempt to connect a call.
+                               After this duration, any intercom calls that have not been answered will be hung up by the
+                               system.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Places outbound calls to the given <replaceable>technology</replaceable>/<replaceable>resource</replaceable>
+                       and dumps them into a conference bridge as muted participants. The original
+                       caller is dumped into the conference as a speaker and the room is
+                       destroyed when the original callers leaves.</para>
+               </description>
+       </application>
+ ***/
 static const char *app_page= "Page";
 
-static const char *page_synopsis = "Pages phones";
-
-static const char *page_descrip =
-"Page(Technology/Resource&Technology2/Resource2[,options][,timeout])\n"
-"  Places outbound calls to the given technology / resource and dumps\n"
-"them into a conference bridge as muted participants.  The original\n"
-"caller is dumped into the conference as a speaker and the room is\n"
-"destroyed when the original caller leaves.  Valid options are:\n"
-"        d - full duplex audio\n"
-"        q - quiet, do not play beep to caller\n"
-"        r - record the page into a file (see 'r' for app_meetme)\n"
-"        s - only dial channel if devicestate says it is not in use\n"
-"The timeout parameter specifies the length of time that the system\n"
-"will attempt to connect a call. After this duration, any intercom\n"
-"calls that have not been answered will be hung up by the system.\n";
-
 enum {
        PAGE_DUPLEX = (1 << 0),
        PAGE_QUIET = (1 << 1),
@@ -216,7 +249,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       return ast_register_application(app_page, page_exec, page_synopsis, page_descrip);
+       return ast_register_application_xml(app_page, page_exec);
 }
 
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Page Multiple Phones");
index 4e6c3f530a01f5e3e9d07b299658915a2f3f951b..63dd308579ea5210373d23e4d41354f1fa7fad27 100644 (file)
@@ -39,26 +39,49 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/say.h"      /* provides config-file based 'say' functions */
 #include "asterisk/cli.h"
 
-static char *app = "Playback";
-
-static char *synopsis = "Play a file";
-
-static char *descrip = 
-"  Playback(filename[&filename2...][,option]):  Plays back given filenames (do not put\n"
-"extension). Options may also be included following a comma.\n"
-"The 'skip' option causes the playback of the message to be skipped if the channel\n"
-"is not in the 'up' state (i.e. it hasn't been  answered  yet). If 'skip' is \n"
-"specified, the application will return immediately should the channel not be\n"
-"off hook.  Otherwise, unless 'noanswer' is specified, the channel will\n"
-"be answered before the sound is played. Not all channels support playing\n"
-"messages while still on hook.\n"
-"This application sets the following channel variable upon completion:\n"
-" PLAYBACKSTATUS    The status of the playback attempt as a text string, one of\n"
-"               SUCCESS | FAILED\n"
-"See Also: Background (application) -- for playing soundfiles that are interruptible\n"
-"          WaitExten (application) -- wait for digits from caller, optionally play music on hold\n"
-;
+/*** DOCUMENTATION
+       <application name="Playback" language="en_US">
+               <synopsis>
+                       Play a file.
+               </synopsis>
+               <syntax>
+                       <parameter name="filenames" required="true" argsep="&amp;">
+                               <argument name="filename" required="true" />
+                               <argument name="filename2" multiple="true" />
+                       </parameter>
+                       <parameter name="options">
+                               <para>Comma separated list of options</para>
+                               <optionlist>
+                                       <option name="skip">
+                                               <para>Do not play if not answered</para>
+                                       </option>
+                                       <option name="noanswer">
+                                               <para>Playback without answering, otherwise the channel will
+                                               be answered before the sound is played.</para>
+                                               <note><para>Not all channel types support playing messages while still on hook.</para></note>
+                                       </option>
+                               </optionlist>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Plays back given filenames (do not put extension of wav/alaw etc).
+                       The playback command answer the channel if no options are specified.
+                       If the file is non-existant it will fail</para>
+                       <para>This application sets the following channel variable upon completion:</para>
+                       <variablelist>
+                               <variable name="PLAYBACKSTATUS">
+                                       <para>The status of the playback attempt as a text string.</para>
+                                       <value name="SUCCESS"/>
+                                       <value name="FAILED"/>
+                               </variable>
+                       </variablelist>
+                       <para>See Also: Background (application) -- for playing soundfiles that are interruptible</para>
+                       <para>WaitExten (application) -- wait for digits from caller, optionally play music on hold</para>
+               </description>
+       </application>
+ ***/
 
+static char *app = "Playback";
 
 static struct ast_config *say_cfg = NULL;
 /* save the say' api calls.
@@ -520,7 +543,7 @@ static int load_module(void)
        }
 
        ast_cli_register_multiple(cli_playback, sizeof(cli_playback) / sizeof(struct ast_cli_entry));
-       return ast_register_application(app, playback_exec, synopsis, descrip);
+       return ast_register_application_xml(app, playback_exec);
 }
 
 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Sound File Playback Application",
index 09f698861bf8ab7c57f1f8864ea7e25c40a2d543..71811de1cd0b259d760ebd367d89475ec250e85b 100644 (file)
@@ -41,25 +41,41 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/app.h"
 #include "asterisk/config.h"
 
-static char *app = "PrivacyManager";
-
-static char *synopsis = "Require phone number to be entered, if no CallerID sent";
+/*** DOCUMENTATION
+       <application name="PrivacyManager" language="en_US">
+               <synopsis>
+                       Require phone number to be entered, if no CallerID sent
+               </synopsis>
+               <syntax>
+                       <parameter name="maxretries">
+                               <para>Total tries caller is allowed to input a callerid. Defaults to <literal>3</literal>.</para>
+                       </parameter>
+                       <parameter name="minlength">
+                               <para>Minimum allowable digits in the input callerid number. Defaults to <literal>10</literal>.</para>
+                       </parameter>
+                       <parameter name="context">
+                               <para>Context to check the given callerid against patterns.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>If no Caller*ID is sent, PrivacyManager answers the channel and asks
+                       the caller to enter their phone number. The caller is given
+                       <replaceable>maxretries</replaceable> attempts to do so. The application does
+                       <emphasis>nothing</emphasis> if Caller*ID was received on the channel.</para>
+                       <para>The application sets the following channel variable upon completion:</para>
+                       <variablelist>
+                               <variable name="PRIVACYMGRSTATUS">
+                                       <para>The status of the privacy manager's attempt to collect a phone number from the user.</para>
+                                       <value name="SUCCESS"/>
+                                       <value name="FAILED"/>
+                               </variable>
+                       </variablelist>
+               </description>
+       </application>
+ ***/
 
-static char *descrip =
-  "  PrivacyManager([maxretries][,minlength][,context]): If no Caller*ID \n"
-  "is sent, PrivacyManager answers the channel and asks the caller to\n"
-  "enter their phone number. The caller is given 'maxretries' attempts to do so.\n"
-  "The application does nothing if Caller*ID was received on the channel.\n"
-  "   maxretries  default 3  -maximum number of attempts the caller is allowed \n"
-  "               to input a callerid.\n"
-  "   minlength   default 10 -minimum allowable digits in the input callerid number.\n"
-  "   context     context to check the given Caller*ID against patterns.\n"
-  "The application sets the following channel variable upon completion: \n"
-  "PRIVACYMGRSTATUS  The status of the privacy manager's attempt to collect \n"
-  "                  a phone number from the user. A text string that is either:\n" 
-  "          SUCCESS | FAILED \n"
-;
 
+static char *app = "PrivacyManager";
 
 static int privacy_exec (struct ast_channel *chan, void *data)
 {
@@ -178,7 +194,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       return ast_register_application(app, privacy_exec, synopsis, descrip);
+       return ast_register_application_xml(app, privacy_exec);
 }
 
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Require phone number to be entered, if no CallerID sent");
index 5733d0bc4ff9b5381823db1957eed96cfc8023dd..bc04deb46b13ab5bea17bfddd5aa6fbf41f41cc3 100644 (file)
@@ -108,6 +108,344 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  * to this order!
  */
 
+/*** DOCUMENTATION
+       <application name="Queue" language="en_US">
+               <synopsis>
+                       Queue a call for a call queue.
+               </synopsis>
+               <syntax>
+                       <parameter name="queuename" required="true" />
+                       <parameter name="options">
+                               <optionlist>
+                                       <option name="c">
+                                               <para>Continue in the dialplan if the callee hangs up.</para>
+                                       </option>
+                                       <option name="d">
+                                               <para>data-quality (modem) call (minimum delay).</para>
+                                       </option>
+                                       <option name="h">
+                                               <para>Allow <emphasis>callee</emphasis> to hang up by pressing <literal>*</literal>.</para>
+                                       </option>
+                                       <option name="H">
+                                               <para>Allow <emphasis>caller</emphasis> to hang up by pressing <literal>*</literal>.</para>
+                                       </option>
+                                       <option name="n">
+                                               <para>No retries on the timeout; will exit this application and
+                                               go to the next step.</para>
+                                       </option>
+                                       <option name="i">
+                                               <para>Ignore call forward requests from queue members and do nothing
+                                               when they are requested.</para>
+                                       </option>
+                                       <option name="r">
+                                               <para>Ring instead of playing MOH. Periodic Announcements are still made, if applicable.</para>
+                                       </option>
+                                       <option name="t">
+                                               <para>Allow the <emphasis>called</emphasis> user to transfer the calling user.</para>
+                                       </option>
+                                       <option name="T">
+                                               <para>Allow the <emphasis>calling</emphasis> user to transfer the call.</para>
+                                       </option>
+                                       <option name="w">
+                                               <para>Allow the <emphasis>called</emphasis> user to write the conversation to
+                                               disk via Monitor.</para>
+                                       </option>
+                                       <option name="W">
+                                               <para>Allow the <emphasis>calling</emphasis> user to write the conversation to
+                                               disk via Monitor.</para>
+                                       </option>
+                                       <option name="k">
+                                               <para>Allow the <emphasis>called</emphasis> party to enable parking of the call by sending
+                                               the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
+                                       </option>
+                                       <option name="K">
+                                               <para>Allow the <emphasis>calling</emphasis> party to enable parking of the call by sending
+                                               the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
+                                       </option>
+                                       <option name="x">
+                                               <para>Allow the <emphasis>called</emphasis> user to write the conversation
+                                               to disk via MixMonitor.</para>
+                                       </option>
+                                       <option name="X">
+                                               <para>Allow the <emphasis>calling</emphasis> user to write the conversation to
+                                               disk via MixMonitor.</para>
+                                       </option>
+                               </optionlist>
+                       </parameter>
+                       <parameter name="URL">
+                               <para><replaceable>URL</replaceable> will be sent to the called party if the channel supports it.</para>
+                       </parameter>
+                       <parameter name="announceoverride" />
+                       <parameter name="timeout">
+                               <para>Will cause the queue to fail out after a specified number of
+                               seconds, checked between each <filename>queues.conf</filename> <replaceable>timeout</replaceable> and
+                               <replaceable>retry</replaceable> cycle.</para>
+                       </parameter>
+                       <parameter name="AGI">
+                               <para>Will setup an AGI script to be executed on the calling party's channel once they are
+                               connected to a queue member.</para>
+                       </parameter>
+                       <parameter name="macro">
+                               <para>Will run a macro on the calling party's channel once they are connected to a queue member.</para>
+                       </parameter>
+                       <parameter name="gosub">
+                               <para>Will run a gosub on the calling party's channel once they are connected to a queue member.</para>
+                       </parameter>
+                       <parameter name="rule">
+                               <para>Will cause the queue's defaultrule to be overridden by the rule specified.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>In addition to transferring the call, a call may be parked and then picked
+                       up by another user.</para>
+                       <para>This application will return to the dialplan if the queue does not exist, or
+                       any of the join options cause the caller to not enter the queue.</para>
+                       <para>This application sets the following channel variable upon completion:</para>
+                       <variablelist>
+                               <variable name="QUEUESTATUS">
+                                       <para>The status of the call as a text string.</para>
+                                       <value name="TIMEOUT" />
+                                       <value name="FULL" />
+                                       <value name="JOINEMPTY" />
+                                       <value name="LEAVEEMPTY" />
+                                       <value name="JOINUNAVAIL" />
+                                       <value name="LEAVEUNAVAIL" />
+                                       <value name="CONTINUE" />
+                               </variable>
+                       </variablelist>
+               </description>
+       </application>
+       <application name="AddQueueMember" language="en_US">
+               <synopsis>
+                       Dynamically adds queue members.
+               </synopsis>
+               <syntax>
+                       <parameter name="queuename" required="true" />
+                       <parameter name="interface" />
+                       <parameter name="penalty" />
+                       <parameter name="options" />
+                       <parameter name="membername" />
+                       <parameter name="stateinterface" />
+               </syntax>
+               <description>
+                       <para>Dynamically adds interface to an existing queue. If the interface is
+                       already in the queue it will return an error.</para>
+                       <para>This application sets the following channel variable upon completion:</para>
+                       <variablelist>
+                               <variable name="AQMSTATUS">
+                                       <para>The status of the attempt to add a queue member as a text string.</para>
+                                       <value name="ADDED" />
+                                       <value name="MEMBERALREADY" />
+                                       <value name="NOSUCHQUEUE" />
+                               </variable>
+                       </variablelist>
+               </description>
+       </application>
+       <application name="RemoveQueueMember" language="en_US">
+               <synopsis>
+                       Dynamically removes queue members.
+               </synopsis>
+               <syntax>
+                       <parameter name="queuename" required="true" />
+                       <parameter name="interface" />
+                       <parameter name="options" />
+               </syntax>
+               <description>
+                       <para>If the interface is <emphasis>NOT</emphasis> in the queue it will return an error.</para>
+                       <para>This application sets the following channel variable upon completion:</para>
+                       <variablelist>
+                               <variable name="RQMSTATUS">
+                                       <value name="REMOVED" />
+                                       <value name="NOTINQUEUE" />
+                                       <value name="NOSUCHQUEUE" />
+                               </variable>
+                       </variablelist>
+                       <para>Example: RemoveQueueMember(techsupport,SIP/3000)</para>
+               </description>
+       </application>
+       <application name="PauseQueueMember" language="en_US">
+               <synopsis>
+                       Pauses a queue member.
+               </synopsis>
+               <syntax>
+                       <parameter name="queuename" />
+                       <parameter name="interface" required="true" />
+                       <parameter name="options" />
+                       <parameter name="reason">
+                               <para>Is used to add extra information to the appropriate queue_log entries and manager events.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Pauses (blocks calls for) a queue member. The given interface will be paused in the given queue.
+                       This prevents any calls from being sent from the queue to the interface until it is
+                       unpaused with UnpauseQueueMember or the manager interface.  If no queuename is given,
+                       the interface is paused in every queue it is a member of. The application will fail if the
+                       interface is not found.</para>
+                       <para>This application sets the following channel variable upon completion:</para>
+                       <variablelist>
+                               <variable name="PQMSTATUS">
+                                       <para>The status of the attempt to pause a queue member as a text string.</para>
+                                       <value name="PAUSED" />
+                                       <value name="NOTFOUND" />
+                               </variable>
+                       </variablelist>
+                       <para>Example: PauseQueueMember(,SIP/3000)</para>
+               </description>
+       </application>
+       <application name="UnpauseQueueMember" language="en_US">
+               <synopsis>
+                       Unpauses a queue member.                
+               </synopsis>
+               <syntax>
+                       <parameter name="queuename" />
+                       <parameter name="interface" required="true" />
+                       <parameter name="options" />
+                       <parameter name="reason">
+                               <para>Is used to add extra information to the appropriate queue_log entries and manager events.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Unpauses (resumes calls to) a queue member. This is the counterpart to <literal>PauseQueueMember()</literal>
+                       and operates exactly the same way, except it unpauses instead of pausing the given interface.</para>
+                       <para>This application sets the following channel variable upon completion:</para>
+                       <variablelist>
+                               <variable name="UPQMSTATUS">
+                                       <para>The status of the attempt to unpause a queue member as a text string.</para>
+                                       <value name="UNPAUSED" />
+                                       <value name="NOTFOUND" />
+                               </variable>
+                       </variablelist>
+                       <para>Example: UnpauseQueueMember(,SIP/3000)</para>
+               </description>
+       </application>
+       <application name="QueueLog" language="en_US">
+               <synopsis>
+                       Writes to the queue_log file.
+               </synopsis>
+               <syntax>
+                       <parameter name="queuename" required="true" />
+                       <parameter name="uniqueid" required="true" />
+                       <parameter name="agent" required="true" />
+                       <parameter name="event" required="true" />
+                       <parameter name="additionalinfo" />
+               </syntax>
+               <description>
+                       <para>Allows you to write your own events into the queue log.</para>
+                       <para>Example: QueueLog(101,${UNIQUEID},${AGENT},WENTONBREAK,600)</para>
+               </description>
+       </application>
+       <function name="QUEUE_VARIABLES" language="en_US">
+               <synopsis>
+                       Return Queue information in variables.
+               </synopsis>
+               <syntax>
+                       <parameter name="queuename" required="true">
+                               <enumlist>
+                                       <enum name="QUEUEMAX">
+                                               <para>Maxmimum number of calls allowed.</para>
+                                       </enum>
+                                       <enum name="QUEUESTRATEGY">
+                                               <para>The strategy of the queue.</para>
+                                       </enum>
+                                       <enum name="QUEUECALLS">
+                                               <para>Number of calls currently in the queue.</para>
+                                       </enum>
+                                       <enum name="QUEUEHOLDTIME">
+                                               <para>Current average hold time.</para>
+                                       </enum>
+                                       <enum name="QUEUECOMPLETED">
+                                               <para>Number of completed calls for the queue.</para>
+                                       </enum>
+                                       <enum name="QUEUEABANDONED">
+                                               <para>Number of abandoned calls.</para>
+                                       </enum>
+                                       <enum name="QUEUESRVLEVEL">
+                                               <para>Queue service level.</para>
+                                       </enum>
+                                       <enum name="QUEUESRVLEVELPERF">
+                                               <para>Current service level performance.</para>
+                                       </enum>
+                               </enumlist>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Makes the following queue variables available.</para>
+                       <para>Returns <literal>0</literal> if queue is found and setqueuevar is defined, <literal>-1</literal> otherwise.</para>
+               </description>
+       </function>
+       <function name="QUEUE_MEMBER" language="en_US">
+               <synopsis>
+                       Count number of members answering a queue.
+               </synopsis>
+               <syntax>
+                       <parameter name="queuename" required="true" />
+                       <parameter name="option" required="true">
+                               <enumlist>
+                                       <enum name="logged">
+                                               <para>Returns the number of logged-in members for the specified queue.</para>
+                                       </enum>
+                                       <enum name="free">
+                                               <para>Returns the number of logged-in members for the specified queue available to take a call.</para>
+                                       </enum>
+                                       <enum name="count">
+                                               <para>Returns the total number of members for the specified queue.</para>
+                                       </enum>
+                               </enumlist>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Returns the number of members currently associated with the specified <replaceable>queuename</replaceable>.</para>
+               </description>
+       </function>
+       <function name="QUEUE_MEMBER_COUNT" language="en_US">
+               <synopsis>
+                       Count number of members answering a queue.
+               </synopsis>
+               <syntax>
+                       <parameter name="queuename" required="true" />
+               </syntax>
+               <description>
+                       <para>Returns the number of members currently associated with the specified <replaceable>queuename</replaceable>.</para>
+                       <warning><para>This function has been deprecated in favor of the <literal>QUEUE_MEMBER()</literal> function</para></warning>
+               </description>
+       </function>
+       <function name="QUEUE_WAITING_COUNT" language="en_US">
+               <synopsis>
+                       Count number of calls currently waiting in a queue.
+               </synopsis>
+               <syntax>
+                       <parameter name="queuename" />
+               </syntax>
+               <description>
+                       <para>Returns the number of callers currently waiting in the specified <replaceable>queuename</replaceable>.</para>
+               </description>
+       </function>
+       <function name="QUEUE_MEMBER_LIST" language="en_US">
+               <synopsis>
+                       Returns a list of interfaces on a queue.
+               </synopsis>
+               <syntax>
+                       <parameter name="queuename" required="true" />
+               </syntax>
+               <description>
+                       <para>Returns a comma-separated list of members associated with the specified <replaceable>queuename</replaceable>.</para>
+               </description>
+       </function>
+       <function name="QUEUE_MEMBER_PENALTY" language="en_US">
+               <synopsis>
+                       Gets or sets queue members penalty.
+               </synopsis>
+               <syntax>
+                       <parameter name="queuename" required="true" />
+                       <parameter name="interface" required="true" />
+               </syntax>
+               <description>
+                       <para>Gets or sets queue members penalty.</para>
+               </description>
+       </function>
+
+ ***/
+
 enum {
        QUEUE_STRATEGY_RINGALL = 0,
        QUEUE_STRATEGY_LEASTRECENT,
@@ -150,128 +488,15 @@ static struct ast_taskprocessor *devicestate_tps;
 
 static char *app = "Queue";
 
-static char *synopsis = "Queue a call for a call queue";
-
-static char *descrip =
-"  Queue(queuename[,options[,URL][,announceoverride][,timeout][,AGI][,macro][,gosub][,rule]):\n"
-"Queues an incoming call in a particular call queue as defined in queues.conf.\n"
-"This application will return to the dialplan if the queue does not exist, or\n"
-"any of the join options cause the caller to not enter the queue.\n"
-"The option string may contain zero or more of the following characters:\n"
-"      'c' -- continue in the dialplan if the callee hangs up.\n"
-"      'd' -- data-quality (modem) call (minimum delay).\n"
-"      'h' -- allow callee to hang up by hitting '*', or whatver disconnect sequence\n"
-"             that is defined in the featuremap section in features.conf.\n"
-"      'H' -- allow caller to hang up by hitting '*', or whatever disconnect sequence\n"
-"             that is defined in the featuremap section in features.conf.\n"
-"      'n' -- no retries on the timeout; will exit this application and \n"
-"             go to the next step.\n"
-"      'i' -- ignore call forward requests from queue members and do nothing\n"
-"             when they are requested.\n"
-"      'r' -- ring instead of playing MOH. Periodic Announcements are still made, if applicable.\n"
-"      't' -- allow the called user transfer the calling user by pressing '#' or\n"
-"             whatever blindxfer sequence defined in the featuremap section in\n"
-"             features.conf\n"
-"      'T' -- to allow the calling user to transfer the call by pressing '#' or\n"
-"             whatever blindxfer sequence defined in the featuremap section in\n"
-"             features.conf\n"
-"      'w' -- allow the called user to write the conversation to disk via Monitor\n"
-"             by pressing the automon sequence defined in the featuremap section in\n"
-"             features.conf\n"
-"      'W' -- allow the calling user to write the conversation to disk via Monitor\n"
-"             by pressing the automon sequence defined in the featuremap section in\n"
-"             features.conf\n"
-"      'k' -- Allow the called party to enable parking of the call by sending\n"
-"             the DTMF sequence defined for call parking in features.conf.\n"
-"      'K' -- Allow the calling party to enable parking of the call by sending\n"
-"             the DTMF sequence defined for call parking in features.conf.\n"
-"      'x' -- allow the called user to write the conversation to disk via MixMonitor\n"
-"             by pressing the automixmon sequence defined in the featuremap section in\n"
-"             features.conf\n"
-"      'X' -- allow the calling user to write the conversation to disk via MixMonitor\n"
-"             by pressing the automixmon sequence defined in the featuremap section in\n"
-"             features.conf\n"
-"  The optional URL will be sent to the called party if the channel supports\n"
-"it.\n"
-"  The optional AGI parameter will setup an AGI script to be executed on the \n"
-"calling party's channel once they are connected to a queue member.\n"
-"  The optional macro parameter will run a macro on the \n"
-"calling party's channel once they are connected to a queue member.\n"
-"  The optional gosub parameter will run a gosub on the \n"
-"calling party's channel once they are connected to a queue member.\n"
-"  The optional rule parameter will cause the queue's defaultrule to be\n"
-"overridden by the rule specified.\n"
-"  The timeout will cause the queue to fail out after a specified number of\n"
-"seconds, checked between each queues.conf 'timeout' and 'retry' cycle.\n"
-"  This application sets the following channel variable upon completion:\n"
-"      QUEUESTATUS    The status of the call as a text string, one of\n"
-"             TIMEOUT | FULL | JOINEMPTY | LEAVEEMPTY | JOINUNAVAIL | LEAVEUNAVAIL | CONTINUE\n";
-
 static char *app_aqm = "AddQueueMember" ;
-static char *app_aqm_synopsis = "Dynamically adds queue members" ;
-static char *app_aqm_descrip =
-"   AddQueueMember(queuename[,interface[,penalty[,options[,membername[,stateinterface]]]]]):\n"
-"Dynamically adds interface to an existing queue.\n"
-"If the interface is already in the queue it will return an error.\n"
-"  This application sets the following channel variable upon completion:\n"
-"     AQMSTATUS    The status of the attempt to add a queue member as a \n"
-"                     text string, one of\n"
-"           ADDED | MEMBERALREADY | NOSUCHQUEUE \n"
-"Example: AddQueueMember(techsupport,SIP/3000)\n"
-"";
 
 static char *app_rqm = "RemoveQueueMember" ;
-static char *app_rqm_synopsis = "Dynamically removes queue members" ;
-static char *app_rqm_descrip =
-"   RemoveQueueMember(queuename[,interface[,options]]):\n"
-"Dynamically removes interface to an existing queue\n"
-"If the interface is NOT in the queue it will return an error.\n"
-"  This application sets the following channel variable upon completion:\n"
-"     RQMSTATUS      The status of the attempt to remove a queue member as a\n"
-"                     text string, one of\n"
-"           REMOVED | NOTINQUEUE | NOSUCHQUEUE \n"
-"Example: RemoveQueueMember(techsupport,SIP/3000)\n"
-"";
 
 static char *app_pqm = "PauseQueueMember" ;
-static char *app_pqm_synopsis = "Pauses a queue member" ;
-static char *app_pqm_descrip =
-"   PauseQueueMember([queuename],interface[,options[,reason]]):\n"
-"Pauses (blocks calls for) a queue member.\n"
-"The given interface will be paused in the given queue.  This prevents\n"
-"any calls from being sent from the queue to the interface until it is\n"
-"unpaused with UnpauseQueueMember or the manager interface.  If no\n"
-"queuename is given, the interface is paused in every queue it is a\n"
-"member of. The application will fail if the interface is not found.\n"
-"The reason string is entirely optional and is used to add extra information\n"
-"to the appropriate queue_log entries and manager events.\n"
-"  This application sets the following channel variable upon completion:\n"
-"     PQMSTATUS      The status of the attempt to pause a queue member as a\n"
-"                     text string, one of\n"
-"           PAUSED | NOTFOUND\n"
-"Example: PauseQueueMember(,SIP/3000)\n";
 
 static char *app_upqm = "UnpauseQueueMember" ;
-static char *app_upqm_synopsis = "Unpauses a queue member" ;
-static char *app_upqm_descrip =
-"   UnpauseQueueMember([queuename],interface[,options[,reason]]):\n"
-"Unpauses (resumes calls to) a queue member.\n"
-"This is the counterpart to PauseQueueMember and operates exactly the\n"
-"same way, except it unpauses instead of pausing the given interface.\n"
-"The reason string is entirely optional and is used to add extra information\n"
-"to the appropriate queue_log entries and manager events.\n"
-"  This application sets the following channel variable upon completion:\n"
-"     UPQMSTATUS       The status of the attempt to unpause a queue \n"
-"                      member as a text string, one of\n"
-"            UNPAUSED | NOTFOUND\n"
-"Example: UnpauseQueueMember(,SIP/3000)\n";
 
 static char *app_ql = "QueueLog" ;
-static char *app_ql_synopsis = "Writes to the queue_log" ;
-static char *app_ql_descrip =
-"   QueueLog(queuename,uniqueid,agent,event[,additionalinfo]):\n"
-"Allows you to write your own events into the queue log\n"
-"Example: QueueLog(101,${UNIQUEID},${AGENT},WENTONBREAK,600)\n";
 
 /*! \brief Persistent Members astdb family */
 static const char *pm_family = "Queue/PersistentMembers";
@@ -5088,69 +5313,31 @@ static int queue_function_memberpenalty_write(struct ast_channel *chan, const ch
 
 static struct ast_custom_function queuevar_function = {
        .name = "QUEUE_VARIABLES",
-       .synopsis = "Return Queue information in variables",
-       .syntax = "QUEUE_VARIABLES(<queuename>)",
-       .desc =
-"Makes the following queue variables available.\n"
-"QUEUEMAX maxmimum number of calls allowed\n"
-"QUEUESTRATEGY the strategy of the queue\n"
-"QUEUECALLS number of calls currently in the queue\n"
-"QUEUEHOLDTIME current average hold time\n"
-"QUEUECOMPLETED number of completed calls for the queue\n"
-"QUEUEABANDONED number of abandoned calls\n"
-"QUEUESRVLEVEL queue service level\n"
-"QUEUESRVLEVELPERF current service level performance\n"
-"Returns 0 if queue is found and setqueuevar is defined, -1 otherwise",
        .read = queue_function_var,
 };
 
 static struct ast_custom_function queuemembercount_function = {
        .name = "QUEUE_MEMBER",
-       .synopsis = "Count number of members answering a queue",
-       .syntax = "QUEUE_MEMBER(<queuename>, <option>)",
-       .desc =
-"Returns the number of members currently associated with the specified queue.\n"
-"One of three options may be passed to determine the count returned:\n"
-       "\"logged\" - Returns the number of logged-in members for the specified queue\n"
-       "\"free\" - Returns the number of logged-in members for the specified queue available to take a call\n"
-       "\"count\" - Returns the total number of members for the specified queue\n",
        .read = queue_function_qac,
 };
 
 static struct ast_custom_function queuemembercount_dep = {
        .name = "QUEUE_MEMBER_COUNT",
-       .synopsis = "Count number of members answering a queue",
-       .syntax = "QUEUE_MEMBER_COUNT(<queuename>)",
-       .desc =
-"Returns the number of members currently associated with the specified queue.\n\n"
-"This function has been deprecated in favor of the QUEUE_MEMBER function\n",
        .read = queue_function_qac_dep,
 };
 
 static struct ast_custom_function queuewaitingcount_function = {
        .name = "QUEUE_WAITING_COUNT",
-       .synopsis = "Count number of calls currently waiting in a queue",
-       .syntax = "QUEUE_WAITING_COUNT(<queuename>)",
-       .desc =
-"Returns the number of callers currently waiting in the specified queue.\n",
        .read = queue_function_queuewaitingcount,
 };
 
 static struct ast_custom_function queuememberlist_function = {
        .name = "QUEUE_MEMBER_LIST",
-       .synopsis = "Returns a list of interfaces on a queue",
-       .syntax = "QUEUE_MEMBER_LIST(<queuename>)",
-       .desc =
-"Returns a comma-separated list of members associated with the specified queue.\n",
        .read = queue_function_queuememberlist,
 };
 
 static struct ast_custom_function queuememberpenalty_function = {
        .name = "QUEUE_MEMBER_PENALTY",
-       .synopsis = "Gets or sets queue members penalty.",
-       .syntax = "QUEUE_MEMBER_PENALTY(<queuename>,<interface>)",
-       .desc =
-"Gets or sets queue members penalty\n",
        .read = queue_function_memberpenalty_read,
        .write = queue_function_memberpenalty_write,
 };
@@ -6430,12 +6617,12 @@ static int load_module(void)
                reload_queue_members();
 
        ast_cli_register_multiple(cli_queue, sizeof(cli_queue) / sizeof(struct ast_cli_entry));
-       res = ast_register_application(app, queue_exec, synopsis, descrip);
-       res |= ast_register_application(app_aqm, aqm_exec, app_aqm_synopsis, app_aqm_descrip);
-       res |= ast_register_application(app_rqm, rqm_exec, app_rqm_synopsis, app_rqm_descrip);
-       res |= ast_register_application(app_pqm, pqm_exec, app_pqm_synopsis, app_pqm_descrip);
-       res |= ast_register_application(app_upqm, upqm_exec, app_upqm_synopsis, app_upqm_descrip);
-       res |= ast_register_application(app_ql, ql_exec, app_ql_synopsis, app_ql_descrip);
+       res = ast_register_application_xml(app, queue_exec);
+       res |= ast_register_application_xml(app_aqm, aqm_exec);
+       res |= ast_register_application_xml(app_rqm, rqm_exec);
+       res |= ast_register_application_xml(app_pqm, pqm_exec);
+       res |= ast_register_application_xml(app_upqm, upqm_exec);
+       res |= ast_register_application_xml(app_ql, ql_exec);
        res |= ast_manager_register("Queues", 0, manager_queues_show, "Queues");
        res |= ast_manager_register("QueueStatus", 0, manager_queues_status, "Queue Status");
        res |= ast_manager_register("QueueSummary", 0, manager_queues_summary, "Queue Summary");
index 93ca4e670f4278c8843a22904350c59d512fad3e..e54741ffa60f30dbb99af593594fa88897b6f232 100644 (file)
@@ -36,6 +36,82 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/indications.h"
 #include "asterisk/channel.h"
 
+/*** DOCUMENTATION
+       <application name="ReadExten" language="en_US">
+               <synopsis>
+                       Read an extension into a variable.
+               </synopsis>
+               <syntax>
+                       <parameter name="variable" required="true" />
+                       <parameter name="filename">
+                               <para>File to play before reading digits or tone with option <literal>i</literal></para>
+                       </parameter>
+                       <parameter name="context">
+                               <para>Context in which to match extensions.</para>
+                       </parameter>
+                       <parameter name="option">
+                               <optionlist>
+                                       <option name="s">
+                                               <para>Return immediately if the channel is not answered.</para>
+                                       </option>
+                                       <option name="i">
+                                               <para>Play <replaceable>filename</replaceable> as an indication tone from your
+                                               <filename>indications.conf</filename></para>
+                                       </option>
+                                       <option name="n">
+                                               <para>Read digits even if the channel is not answered.</para>
+                                       </option>
+                               </optionlist>
+                       </parameter>
+                       <parameter name="timeout">
+                               <para>An integer number of seconds to wait for a digit response. If
+                               greater than <literal>0</literal>, that value will override the default timeout.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Reads a <literal>#</literal> terminated string of digits from the user into the given variable.</para>
+                       <para>Will set READEXTENSTATUS on exit with one of the following statuses:</para>
+                       <variablelist>
+                               <variable name="READEXTENSTATUS">
+                                       <value name="OK">
+                                               A valid extension exists in ${variable}.
+                                       </value>
+                                       <value name="TIMEOUT">
+                                               No extension was entered in the specified time.
+                                       </value>
+                                       <value name="INVALID">
+                                               An invalid extension, ${INVALID_EXTEN}, was entered.
+                                       </value>
+                                       <value name="SKIP">
+                                               Line was not up and the option 's' was specified.
+                                       </value>
+                                       <value name="ERROR">
+                                               Invalid arguments were passed.
+                                       </value>
+                               </variable>
+                       </variablelist>
+               </description>
+       </application>
+       <function name="VALID_EXTEN" language="en_US">
+               <synopsis>
+                       Determine whether an extension exists or not.
+               </synopsis>
+               <syntax>
+                       <parameter name="context">
+                               <para>Defaults to the current context</para>
+                       </parameter>
+                       <parameter name="extension" required="true" />
+                       <parameter name="priority">
+                               <para>Priority defaults to <literal>1</literal>.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Returns a true value if the indicated <replaceable>context</replaceable>,
+                       <replaceable>extension</replaceable>, and <replaceable>priority</replaceable> exist.</para>
+               </description>
+       </function>
+ ***/
+
 enum {
        OPT_SKIP = (1 << 0),
        OPT_INDICATION = (1 << 1),
@@ -50,28 +126,6 @@ AST_APP_OPTIONS(readexten_app_options, {
 
 static char *app = "ReadExten";
 
-static char *synopsis = "Read an extension into a variable";
-
-static char *descrip = 
-"  ReadExten(<variable>[,[<filename>][,[<context>][,[<option>][,<timeout>]]]])\n\n"
-"Reads a #-terminated string of digits from the user into the given variable.\n"
-"  filename  file to play before reading digits or tone with option i\n"
-"  context   context in which to match extensions\n"
-"  option    options are:\n"
-"              s - Return immediately if the channel is not answered,\n"
-"              i - Play filename as an indication tone from your\n"
-"                  indications.conf\n"
-"              n - Read digits even if the channel is not answered.\n"
-"  timeout   An integer number of seconds to wait for a digit response. If\n"
-"            greater than 0, that value will override the default timeout.\n\n"
-"ReadExten will set READEXTENSTATUS on exit with one of the following statuses:\n"
-"  OK        A valid extension exists in ${variable}\n"
-"  TIMEOUT   No extension was entered in the specified time\n"
-"  INVALID   An invalid extension, ${INVALID_EXTEN}, was entered\n"
-"  SKIP      Line was not up and the option 's' was specified\n"
-"  ERROR     Invalid arguments were passed\n";
-
-
 static int readexten_exec(struct ast_channel *chan, void *data)
 {
        int res = 0;
@@ -232,11 +286,6 @@ static int acf_isexten_exec(struct ast_channel *chan, const char *cmd, char *par
 
 static struct ast_custom_function acf_isexten = {
        .name = "VALID_EXTEN",
-       .synopsis = "Determine whether an extension exists or not",
-       .syntax = "VALID_EXTEN([<context>],<extension>[,<priority>])",
-       .desc =
-"Returns a true value if the indicated context, extension, and priority exist.\n"
-"Context defaults to the current context, priority defaults to 1.\n",
        .read = acf_isexten_exec,
 };
 
@@ -250,7 +299,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       int res = ast_register_application(app, readexten_exec, synopsis, descrip);
+       int res = ast_register_application_xml(app, readexten_exec);
        res |= ast_custom_function_register(&acf_isexten);
        return res;
 }
index 8762ef860cffb38f4ce31ebd93aba9c7c212439b..c5234089f0d2b87260fe1c2e533fb33f7230ad7c 100644 (file)
@@ -35,16 +35,33 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/app.h"
 #include "asterisk/module.h"
 
-static char *app_readfile = "ReadFile";
-
-static char *readfile_synopsis = "Read the contents of a text file into a channel variable";
-
-static char *readfile_descrip =
-"ReadFile(varname=file,length)\n"
-"  varname  - Result stored here.\n"
-"  file     - The name of the file to read.\n"
-"  length   - Maximum number of characters to capture.\n";
+/*** DOCUMENTATION
+       <application name="ReadFile" language="en_US">
+               <synopsis>
+                       Read the contents of a text file into a channel variable.
+               </synopsis>
+               <syntax argsep="=">
+                       <parameter name="varname" required="true">
+                               <para>Result stored here.</para>
+                       </parameter>
+                       <parameter name="fileparams" required="true">
+                               <argument name="file" required="true">
+                                       <para>The name of the file to read.</para>
+                               </argument>
+                               <argument name="length" required="false">
+                                       <para>Maximum number of characters to capture.</para>
+                                       <para>If not specified defaults to max.</para>
+                               </argument>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Read the contents of a text file into channel variable <replaceable>varname</replaceable></para>
+                       <warning><para>ReadFile has been deprecated in favor of Set(varname=${FILE(file,0,length)})</para></warning>
+               </description>
+       </application>
+ ***/
 
+static char *app_readfile = "ReadFile";
 
 static int readfile_exec(struct ast_channel *chan, void *data)
 {
@@ -101,7 +118,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       return ast_register_application(app_readfile, readfile_exec, readfile_synopsis, readfile_descrip);
+       return ast_register_application_xml(app_readfile, readfile_exec);
 }
 
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Stores output of file into a variable");
index 8afafc93db07954d5876a235d32f598ece3e09a1..a575efdbe1991670c971445bfdae54646e47a346 100644 (file)
@@ -36,35 +36,66 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/channel.h"
 #include "asterisk/dsp.h"      /* use dsp routines for silence detection */
 
+/*** DOCUMENTATION
+       <application name="Record" language="en_US">
+               <synopsis>
+                       Record to a file.
+               </synopsis>
+               <syntax>
+                       <parameter name="filename" required="true" argsep=".">
+                               <argument name="filename" required="true" />
+                               <argument name="format" required="true">
+                                       <para>Is the format of the file type to be recorded (wav, gsm, etc).</para>
+                               </argument>
+                       </parameter>
+                       <parameter name="silence">
+                               <para>Is the number of seconds of silence to allow before returning.</para>
+                       </parameter>
+                       <parameter name="maxduration">
+                               <para>Is the maximum recording duration in seconds. If missing
+                               or 0 there is no maximum.</para>
+                       </parameter>
+                       <parameter name="options">
+                               <optionlist>
+                                       <option name="a">
+                                               <para>Append to existing recording rather than replacing.</para>
+                                       </option>
+                                       <option name="n">
+                                               <para>Do not answer, but record anyway if line not yet answered.</para>
+                                       </option>
+                                       <option name="q">
+                                               <para>quiet (do not play a beep tone).</para>
+                                       </option>
+                                       <option name="s">
+                                               <para>skip recording if the line is not yet answered.</para>
+                                       </option>
+                                       <option name="t">
+                                               <para>use alternate '*' terminator key (DTMF) instead of default '#'</para>
+                                       </option>
+                                       <option name="x">
+                                               <para>Ignore all terminator keys (DTMF) and keep recording until hangup.</para>
+                                       </option>
+                               </optionlist>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>If filename contains <literal>%d</literal>, these characters will be replaced with a number
+                       incremented by one each time the file is recorded.
+                       Use <astcli>core show file formats</astcli> to see the available formats on your system
+                       User can press <literal>#</literal> to terminate the recording and continue to the next priority.
+                       If the user hangup during a recording, all data will be lost and the application will teminate.</para>
+                       <variablelist>
+                               <variable name="RECORDED_FILE">
+                                       <para>Will be set to the final filename of the recording.</para>
+                               </variable>
+                       </variablelist>
+               </description>
+       </application>
+
+ ***/
 
 static char *app = "Record";
 
-static char *synopsis = "Record to a file";
-
-static char *descrip = 
-"  Record(filename.format,silence[,maxduration][,options])\n\n"
-"Records from the channel into a given filename. If the file exists it will\n"
-"be overwritten.\n"
-"- 'format' is the format of the file type to be recorded (wav, gsm, etc).\n"
-"- 'silence' is the number of seconds of silence to allow before returning.\n"
-"- 'maxduration' is the maximum recording duration in seconds. If missing\n"
-"or 0 there is no maximum.\n"
-"- 'options' may contain any of the following letters:\n"
-"     'a' : append to existing recording rather than replacing\n"
-"     'n' : do not answer, but record anyway if line not yet answered\n"
-"     'q' : quiet (do not play a beep tone)\n"
-"     's' : skip recording if the line is not yet answered\n"
-"     't' : use alternate '*' terminator key (DTMF) instead of default '#'\n"
-"     'x' : ignore all terminator keys (DTMF) and keep recording until hangup\n"
-"\n"
-"If filename contains '%d', these characters will be replaced with a number\n"
-"incremented by one each time the file is recorded. A channel variable\n"
-"named RECORDED_FILE will also be set, which contains the final filemname.\n\n"
-"Use 'core show file formats' to see the available formats on your system\n\n"
-"User can press '#' to terminate the recording and continue to the next priority.\n\n"
-"If the user should hangup during a recording, all data will be lost and the\n"
-"application will teminate. \n";
-
 enum {
        OPTION_APPEND = (1 << 0),
        OPTION_NOANSWER = (1 << 1),
@@ -359,7 +390,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       return ast_register_application(app, record_exec, synopsis, descrip);
+       return ast_register_application_xml(app, record_exec);
 }
 
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Trivial Record Application");
index d0e23449ed0e9c78dbe78433f172f6e08b52379b..f6122e40d5b29f49dc9e81da7dbd791117b459aa 100644 (file)
@@ -36,29 +36,54 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/say.h"
 #include "asterisk/app.h"
 
+/*** DOCUMENTATION
+       <application name="SayUnixTime" language="en_US">
+               <synopsis>
+                       Says a specified time in a custom format.
+               </synopsis>
+               <syntax>
+                       <parameter name="unixtime">
+                               <para>time, in seconds since Jan 1, 1970.  May be negative. Defaults to now.</para>
+                       </parameter>
+                       <parameter name="timezone">
+                               <para>timezone, see <directory>/usr/share/zoneinfo</directory> for a list. Defaults to machine default.</para>
+                       </parameter>
+                       <parameter name="format">
+                               <para>a format the time is to be said in.  See <filename>voicemail.conf</filename>.
+                               Defaults to <literal>ABdY "digits/at" IMp</literal></para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Uses some of the sound files stored in <directory>/var/lib/asterisk/sounds</directory> to construct a phrase 
+                       saying the specified date and/or time in the specified format. </para>
+               </description>
+       </application>
+       <application name="DateTime" language="en_US">
+               <synopsis>
+                       Says a specified time in a custom format.
+               </synopsis>
+               <syntax>
+                       <parameter name="unixtime">
+                               <para>time, in seconds since Jan 1, 1970.  May be negative. Defaults to now.</para>
+                       </parameter>
+                       <parameter name="timezone">
+                               <para>timezone, see <filename>/usr/share/zoneinfo</filename> for a list. Defaults to machine default.</para>
+                       </parameter>
+                       <parameter name="format">
+                               <para>a format the time is to be said in.  See <filename>voicemail.conf</filename>.
+                               Defaults to <literal>ABdY "digits/at" IMp</literal></para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Say the date and time in a specified format.</para>
+               </description>
+       </application>
+
+ ***/
+
 static char *app_sayunixtime = "SayUnixTime";
 static char *app_datetime = "DateTime";
 
-static char *sayunixtime_synopsis = "Says a specified time in a custom format";
-
-static char *sayunixtime_descrip =
-"SayUnixTime([unixtime][,[timezone][,format]])\n"
-"  unixtime  - time, in seconds since Jan 1, 1970.  May be negative.\n"
-"              defaults to now.\n"
-"  timezone  - timezone, see /usr/share/zoneinfo for a list.\n"
-"              defaults to machine default.\n"
-"  format    - a format the time is to be said in.  See voicemail.conf.\n"
-"              defaults to \"ABdY 'digits/at' IMp\"\n";
-static char *datetime_descrip =
-"DateTime([unixtime][,[timezone][,format]])\n"
-"  unixtime  - time, in seconds since Jan 1, 1970.  May be negative.\n"
-"              defaults to now.\n"
-"  timezone  - timezone, see /usr/share/zoneinfo for a list.\n"
-"              defaults to machine default.\n"
-"  format:   - a format the time is to be said in.  See voicemail.conf.\n"
-"              defaults to \"ABdY 'digits/at' IMp\"\n";
-
-
 static int sayunixtime_exec(struct ast_channel *chan, void *data)
 {
        AST_DECLARE_APP_ARGS(args,
@@ -103,8 +128,8 @@ static int load_module(void)
 {
        int res;
        
-       res = ast_register_application(app_sayunixtime, sayunixtime_exec, sayunixtime_synopsis, sayunixtime_descrip);
-       res |= ast_register_application(app_datetime, sayunixtime_exec, sayunixtime_synopsis, datetime_descrip);
+       res = ast_register_application_xml(app_sayunixtime, sayunixtime_exec);
+       res |= ast_register_application_xml(app_datetime, sayunixtime_exec);
        
        return res;
 }
index 9863ce01213e38be79f919da9181f65cddd36ace..bd92230bd69823fffedd4c504d708f6f89b7e9dc 100644 (file)
@@ -35,19 +35,30 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/manager.h"
 #include "asterisk/channel.h"
 
+/*** DOCUMENTATION
+       <application name="SendDTMF" language="en_US">
+               <synopsis>
+                       Sends arbitrary DTMF digits
+               </synopsis>
+               <syntax>
+                       <parameter name="digits" required="true">
+                               <para>List of digits 0-9,*#,abcd</para>
+                       </parameter>
+                       <parameter name="timeout_ms" required="false">
+                               <para>Amount of time to wait in ms between tones. (defaults to .25s)</para>
+                       </parameter>
+                       <parameter name="duration_ms" required="false">
+                               <para>Duration of each digit</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>DTMF digits sent to a channel with half second pause</para>
+                       <para>It will pass all digits or terminate if it encounters an error.</para>
+               </description>
+       </application>
+ ***/
 static char *app = "SendDTMF";
 
-static char *synopsis = "Sends arbitrary DTMF digits";
-
-static char *descrip = 
-" SendDTMF(digits[,[timeout_ms][,duration_ms]]): Sends DTMF digits on a channel. \n"
-" Accepted digits: 0-9, *#abcd, (default .25s pause between digits)\n"
-" The application will either pass the assigned digits or terminate if it\n"
-" encounters an error.\n"
-" Optional Params: \n"
-"   timeout_ms: pause between digits.\n"
-"   duration_ms: duration of each digit.\n";
-
 static int senddtmf_exec(struct ast_channel *chan, void *vdata)
 {
        int res = 0;
@@ -121,7 +132,7 @@ static int load_module(void)
        int res;
 
        res = ast_manager_register2( "PlayDTMF", EVENT_FLAG_CALL, manager_play_dtmf, "Play DTMF signal on a specific channel.", mandescr_playdtmf );
-       res |= ast_register_application(app, senddtmf_exec, synopsis, descrip);
+       res |= ast_register_application_xml(app, senddtmf_exec);
 
        return res;
 }
index e95ff6158cef7aaa1df2713f682d5afd7f2a434c..53306aa5ab87a1b4bc25dc42f84504e328a9d390 100644 (file)
@@ -37,19 +37,36 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/module.h"
 #include "asterisk/app.h"
 
-static const char *app = "SendText";
-
-static const char *synopsis = "Send a Text Message";
+/*** DOCUMENTATION
+       <application name="SendText" language="en_US">
+               <synopsis>
+                       Send a Text Message.
+               </synopsis>
+               <syntax>
+                       <parameter name="text" required="true" />
+               </syntax>
+               <description>
+                       <para>Sends <replaceable>text</replaceable> to current channel (callee).</para>
+                       <para>Result of transmission will be stored in the <variable>SENDTEXTSTATUS</variable></para>
+                       <variablelist>
+                               <variable name="SENDTEXTSTATUS">
+                                       <value name="SUCCESS">
+                                               Transmission succeeded.
+                                       </value>
+                                       <value name="FAILURE">
+                                               Transmission failed.
+                                       </value>
+                                       <value name="UNSUPPORTED">
+                                               Text transmission not supported by channel.
+                                       </value>
+                               </variable>
+                       </variablelist>
+                       <note><para>At this moment, text is supposed to be 7 bit ASCII in most channels.</para></note>
+               </description>
+       </application>
+ ***/
 
-static const char *descrip = 
-"  SendText(text): Sends text to current channel (callee).\n"
-"Result of transmission will be stored in the SENDTEXTSTATUS\n"
-"channel variable:\n"
-"      SUCCESS      Transmission succeeded\n"
-"      FAILURE      Transmission failed\n"
-"      UNSUPPORTED  Text transmission not supported by channel\n"
-"\n"
-"At this moment, text is supposed to be 7 bit ASCII in most channels.\n";
+static const char *app = "SendText";
 
 static int sendtext_exec(struct ast_channel *chan, void *data)
 {
@@ -91,7 +108,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       return ast_register_application(app, sendtext_exec, synopsis, descrip);
+       return ast_register_application_xml(app, sendtext_exec);
 }
 
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Send Text Applications");
index f1c9df3cbda6d0b2db88852555bd8ebc3ecd501c..6592249b4a49bf880b9dcea2eb0bbe676dbf8479 100644 (file)
@@ -38,26 +38,51 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/image.h"
 #include "asterisk/callerid.h"
 
-static char *app2 = "SetCallerPres";
-
-static char *synopsis2 = "Set CallerID Presentation";
+/*** DOCUMENTATION
+       <application name="SetCallerPres" language="en_US">
+               <synopsis>
+                       Set CallerID Presentation.
+               </synopsis>
+               <syntax>
+                       <parameter name="presentation" required="true">
+                               <enumlist>
+                                       <enum name="allowed_not_screened">
+                                               <para>Presentation Allowed, Not Screened.</para>
+                                       </enum>
+                                       <enum name="allowed_passed_screen">
+                                               <para>Presentation Allowed, Passed Screen.</para>
+                                       </enum>
+                                       <enum name="allowed_failed_screen">
+                                               <para>Presentation Allowed, Failed Screen.</para>
+                                       </enum>
+                                       <enum name="allowed">
+                                               <para>Presentation Allowed, Network Number.</para>
+                                       </enum>
+                                       <enum name="prohib_not_screened">
+                                               <para>Presentation Prohibited, Not Screened.</para>
+                                       </enum>
+                                       <enum name="prohib_passed_screen">
+                                               <para>Presentation Prohibited, Passed Screen.</para>
+                                       </enum>
+                                       <enum name="prohib_failed_screen">
+                                               <para>Presentation Prohibited, Failed Screen.</para>
+                                       </enum>
+                                       <enum name="prohib">
+                                               <para>Presentation Prohibited, Network Number.</para>
+                                       </enum>
+                                       <enum name="unavailable">
+                                               <para>Number Unavailable.</para>
+                                       </enum>
+                               </enumlist>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Set Caller*ID presentation on a call.</para>
+               </description>
+       </application>
+ ***/
 
-
-static char *descrip2 = 
-"  SetCallerPres(presentation): Set Caller*ID presentation on a call.\n"
-"  Valid presentations are:\n"
-"\n"
-"      allowed_not_screened    : Presentation Allowed, Not Screened\n"
-"      allowed_passed_screen   : Presentation Allowed, Passed Screen\n" 
-"      allowed_failed_screen   : Presentation Allowed, Failed Screen\n" 
-"      allowed                 : Presentation Allowed, Network Number\n"
-"      prohib_not_screened     : Presentation Prohibited, Not Screened\n" 
-"      prohib_passed_screen    : Presentation Prohibited, Passed Screen\n"
-"      prohib_failed_screen    : Presentation Prohibited, Failed Screen\n"
-"      prohib                  : Presentation Prohibited, Network Number\n"
-"      unavailable             : Number Unavailable\n"
-"\n"
-;
+static char *app2 = "SetCallerPres";
 
 static int setcallerid_pres_exec(struct ast_channel *chan, void *data)
 {
@@ -91,7 +116,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       return ast_register_application(app2, setcallerid_pres_exec, synopsis2, descrip2);
+       return ast_register_application_xml(app2, setcallerid_pres_exec);
 }
 
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Set CallerID Presentation Application");
index 44bf152aa1bf1629069ec89f76e1b212fb6ee4d4..338a32f8a6a230ca0cd92ceb74b0d4d0cf172c2a 100644 (file)
@@ -44,11 +44,35 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/lock.h"
 #include "asterisk/app.h"
 
+/*** DOCUMENTATION
+       <application name="Skel" language="en_US">
+               <synopsis>
+                       Simple one line explaination.
+               </synopsis>
+               <syntax>
+                       <parameter name="dummy" required="true"/>
+                       <parameter name="options">
+                               <optionlist>
+                                       <option name="a">
+                                               <para>Option A.</para>
+                                       </option>
+                                       <option name="b">
+                                               <para>Option B.</para>
+                                       </option>
+                                       <option name="c">
+                                               <para>Option C.</para>
+                                       </option>
+                               </optionlist>
+                       </parameter>
+               </syntax>
+               <description>
+               <para>This application is a template to build other applications from. 
+               It shows you the basic structure to create your own Asterisk applications.</para>
+               </description>
+       </application>
+ ***/
+
 static char *app = "Skel";
-static char *synopsis = 
-"Skeleton application.";
-static char *descrip = "This application is a template to build other applications from.\n"
- " It shows you the basic structure to create your own Asterisk applications.\n";
 
 enum {
        OPTION_A = (1 << 0),
@@ -122,7 +146,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       return ast_register_application(app, app_exec, synopsis, descrip) ? 
+       return ast_register_application_xml(app, app_exec) ? 
                AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS;
 }
 
index 7af8525604cbc9a343c7cd2c909785480ba36e89..a7ba753fdfcbba0f8d54a65293c11b21d29ffc73 100644 (file)
@@ -36,13 +36,28 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/lock.h"
 #include "asterisk/app.h"
 
-static char *synopsis = "Soft Hangup Application";
-
-static char *desc = "  SoftHangup(Technology/resource[,options]):\n"
-"Hangs up the requested channel.  If there are no channels to hangup,\n"
-"the application will report it.\n"
-"  Options:\n"
-"     'a'  - hang up all channels on a specified device instead of a single resource\n";
+/*** DOCUMENTATION
+       <application name="SoftHangup" language="en_US">
+               <synopsis>
+                       Hangs up the requested channel.
+               </synopsis>
+               <syntax>
+                       <parameter name="Technology/Resource" required="true" />
+                       <parameter name="options">
+                               <optionlist>
+                                       <option name="a">
+                                               <para>Hang up all channels on a specified device instead of a single resource</para>
+                                       </option>
+                               </optionlist>
+                       </parameter>
+               </syntax>       
+               <description>
+                       <para>Hangs up the requested channel.  If there are no channels to 
+                       hangup, the application will report it.</para>
+               </description>
+       </application>
+
+ ***/
 
 static char *app = "SoftHangup";
 
@@ -114,7 +129,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       return ast_register_application(app, softhangup_exec, synopsis, desc);
+       return ast_register_application_xml(app, softhangup_exec);
 }
 
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Hangs up the requested channel");
index 2e5e6de9e7108525d35416cb10a0fa207d0696de..599c5f1d4b72df9f5d1c495d9e0e1ff2851c204e 100644 (file)
@@ -40,6 +40,70 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/channel.h"
 #include "asterisk/agi.h"
 
+/*** DOCUMENTATION
+       <application name="Gosub" language="en_US">
+               <synopsis>
+                       Jump to label, saving return address.
+               </synopsis>
+               <syntax>
+                       <parameter name="context" />
+                       <parameter name="exten" />
+                       <parameter name="priority" required="true" hasparams="optional">
+                               <argument name="arg1" multiple="true" required="true" />
+                               <argument name="argN" />
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Jumps to the label specified, saving the return address.</para>
+               </description>
+       </application>
+       <application name="GosubIf" language="en_US">
+               <synopsis>
+                       Conditionally jump to label, saving return address.
+               </synopsis>
+               <syntax argsep="?">
+                       <parameter name="condition" required="true" />
+                       <parameter name="destination" required="true" argsep=":">
+                               <argument name="labeliftrue" hasparams="optional">
+                                       <argument name="arg1" required="true" multiple="true" />
+                                       <argument name="argN" />
+                               </argument>
+                               <argument name="labeliffalse" hasparams="optional">
+                                       <argument name="arg1" required="true" multiple="true" />
+                                       <argument name="argN" />
+                               </argument>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>If the condition is true, then jump to labeliftrue.  If false, jumps to
+                       labeliffalse, if specified.  In either case, a jump saves the return point
+                       in the dialplan, to be returned to with a Return.</para>
+               </description>
+       </application>
+       <application name="Return" language="en_US">
+               <synopsis>
+                       Return from gosub routine.
+               </synopsis>
+               <syntax>
+                       <parameter name="value">
+                               <para>Return value.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Jumps to the last label on the stack, removing it. The return <replaceable>value</replaceable>, if
+                       any, is saved in the channel variable <variable>GOSUB_RETVAL</variable>.</para>
+               </description>
+       </application>
+       <application name="StackPop" language="en_US">
+               <synopsis>
+                       Remove one address from gosub stack.
+               </synopsis>
+               <syntax />
+               <description>
+                       <para>Removes last label on the stack, discarding it.</para>
+               </description>
+       </application>
+ ***/
 static int agi_loaded = 0;
 
 static const char *app_gosub = "Gosub";
@@ -47,27 +111,6 @@ static const char *app_gosubif = "GosubIf";
 static const char *app_return = "Return";
 static const char *app_pop = "StackPop";
 
-static const char *gosub_synopsis = "Jump to label, saving return address";
-static const char *gosubif_synopsis = "Conditionally jump to label, saving return address";
-static const char *return_synopsis = "Return from gosub routine";
-static const char *pop_synopsis = "Remove one address from gosub stack";
-
-static const char *gosub_descrip =
-"  Gosub([[context,]exten,]priority[(arg1[,...][,argN])]):\n"
-"Jumps to the label specified, saving the return address.\n";
-static const char *gosubif_descrip =
-"  GosubIf(condition?labeliftrue[(arg1[,...])][:labeliffalse[(arg1[,...])]]):\n"
-"If the condition is true, then jump to labeliftrue.  If false, jumps to\n"
-"labeliffalse, if specified.  In either case, a jump saves the return point\n"
-"in the dialplan, to be returned to with a Return.\n";
-static const char *return_descrip =
-"  Return([return-value]):\n"
-"Jumps to the last label on the stack, removing it.  The return value, if\n"
-"any, is saved in the channel variable GOSUB_RETVAL.\n";
-static const char *pop_descrip =
-"  StackPop():\n"
-"Removes last label on the stack, discarding it.\n";
-
 static void gosub_free(void *data);
 
 static struct ast_datastore_info stack_info = {
@@ -530,10 +573,10 @@ static int load_module(void)
                ast_agi_register(ast_module_info->self, &gosub_agi_command);
        }
 
-       ast_register_application(app_pop, pop_exec, pop_synopsis, pop_descrip);
-       ast_register_application(app_return, return_exec, return_synopsis, return_descrip);
-       ast_register_application(app_gosubif, gosubif_exec, gosubif_synopsis, gosubif_descrip);
-       ast_register_application(app_gosub, gosub_exec, gosub_synopsis, gosub_descrip);
+       ast_register_application_xml(app_pop, pop_exec);
+       ast_register_application_xml(app_return, return_exec);
+       ast_register_application_xml(app_gosubif, gosubif_exec);
+       ast_register_application_xml(app_gosub, gosub_exec);
        ast_custom_function_register(&local_function);
 
        return 0;
index 1f39c5a4ed7c38da02627c8de5ba74e2b46d49e9..688a649da664750896757c28b95c67f92e7105f2 100644 (file)
@@ -34,31 +34,68 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/app.h"
 #include "asterisk/channel.h"  /* autoservice */
 
+/*** DOCUMENTATION
+       <application name="System" language="en_US">
+               <synopsis>
+                       Execute a system command.
+               </synopsis>
+               <syntax>
+                       <parameter name="command" required="true">
+                               <para>Command to execute</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Executes a command  by  using  system(). If the command
+                       fails, the console should report a fallthrough.</para>
+                       <para>Result of execution is returned in the <variable>SYSTEMSTATUS</variable> channel variable:</para>
+                       <variablelist>
+                               <variable name="SYSTEMSTATUS">
+                                       <value name="FAILURE">
+                                               Could not execute the specified command.
+                                       </value>
+                                       <value name="SUCCESS">
+                                               Specified command successfully executed.
+                                       </value>
+                               </variable>
+                       </variablelist>
+               </description>
+       </application>
+       <application name="TrySystem" language="en_US">
+               <synopsis>
+                       Try executing a system command.
+               </synopsis>
+               <syntax>
+                       <parameter name="command" required="true">
+                               <para>Command to execute</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Executes a command  by  using  system().</para>
+                       <para>Result of execution is returned in the <variable>SYSTEMSTATUS</variable> channel variable:</para>
+                       <variablelist>
+                               <variable name="SYSTEMSTATUS">
+                                       <value name="FAILURE">
+                                               Could not execute the specified command.
+                                       </value>
+                                       <value name="SUCCESS">
+                                               Specified command successfully executed.
+                                       </value>
+                                       <value name="APPERROR">
+                                               Specified command successfully executed, but returned error code.
+                                       </value>
+                               </variable>
+                       </variablelist>
+               </description>
+       </application>
+
+ ***/
+
 static char *app = "System";
 
 static char *app2 = "TrySystem";
 
-static char *synopsis = "Execute a system command";
-
-static char *synopsis2 = "Try executing a system command";
-
 static char *chanvar = "SYSTEMSTATUS";
 
-static char *descrip =
-"  System(command): Executes a command  by  using  system(). If the command\n"
-"fails, the console should report a fallthrough. \n"
-"Result of execution is returned in the SYSTEMSTATUS channel variable:\n"
-"   FAILURE    Could not execute the specified command\n"
-"   SUCCESS    Specified command successfully executed\n";
-
-static char *descrip2 =
-"  TrySystem(command): Executes a command  by  using  system().\n"
-"on any situation.\n"
-"Result of execution is returned in the SYSTEMSTATUS channel variable:\n"
-"   FAILURE    Could not execute the specified command\n"
-"   SUCCESS    Specified command successfully executed\n"
-"   APPERROR   Specified command successfully executed, but returned error code\n";
-
 static int system_exec_helper(struct ast_channel *chan, void *data, int failmode)
 {
        int res = 0;
@@ -120,8 +157,8 @@ static int load_module(void)
 {
        int res;
 
-       res = ast_register_application(app2, trysystem_exec, synopsis2, descrip2);
-       res |= ast_register_application(app, system_exec, synopsis, descrip);
+       res = ast_register_application_xml(app2, trysystem_exec);
+       res |= ast_register_application_xml(app, system_exec);
 
        return res;
 }
index 9bc5e84dd1a394f168c32f12bb5e0a5d32963827..a0236b8fc7b5f814cb73bf841652a49ff316d749 100644 (file)
@@ -39,21 +39,39 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/dsp.h"
 #include "asterisk/app.h"
 
-static char *app = "BackgroundDetect";
-
-static char *synopsis = "Background a file with talk detect";
-
-static char *descrip = 
-"  BackgroundDetect(<filename>[,<sil>[,<min>[,<max>[,<analysistime>]]]]):\n"
-"Plays back <filename>, waiting for interruption from a given digit (the digit\n"
-"must start the beginning of a valid extension, or it will be ignored).  During\n"
-"the playback of the file, audio is monitored in the receive direction, and if\n"
-"a period of non-silence which is greater than <min> ms yet less than <max> ms\n"
-"is followed by silence for at least <sil> ms, which occurs during the first\n"
-"<analysistime> ms, then the audio playback is aborted and processing jumps to\n"
-"the <talk> extension, if available.  If unspecified, <sil>, <min>, <max>, and\n"
-"<analysistime> default to 1000, 100, infinity, and infinity respectively.\n";
+/*** DOCUMENTATION
+       <application name="BackGroundDetect" language="en_US">
+               <synopsis>
+                       Background a file with talk detect.
+               </synopsis>
+               <syntax>
+                       <parameter name="filename" required="true" />
+                       <parameter name="sil">
+                               <para>If not specified, defaults to <literal>1000</literal>.</para>
+                       </parameter>
+                       <parameter name="min">
+                               <para>If not specified, defaults to <literal>100</literal>.</para>
+                       </parameter>
+                       <parameter name="max">
+                               <para>If not specified, defaults to <literal>infinity</literal>.</para>
+                       </parameter>
+                       <parameter name="analysistime">
+                               <para>If not specified, defaults to <literal>infinity</literal>.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Plays back <replaceable>filename</replaceable>, waiting for interruption from a given digit (the digit
+                       must start the beginning of a valid extension, or it will be ignored). During
+                       the playback of the file, audio is monitored in the receive direction, and if
+                       a period of non-silence which is greater than <replaceable>min</replaceable> ms yet less than
+                       <replaceable>max</replaceable> ms is followed by silence for at least <replaceable>sil</replaceable> ms,
+                       which occurs during the first <replaceable>analysistime</replaceable> ms, then the audio playback is
+                       aborted and processing jumps to the <replaceable>talk</replaceable> extension, if available.</para>
+               </description>
+       </application>
+ ***/
 
+static char *app = "BackgroundDetect";
 
 static int background_detect_exec(struct ast_channel *chan, void *data)
 {
@@ -227,7 +245,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       return ast_register_application(app, background_detect_exec, synopsis, descrip);
+       return ast_register_application_xml(app, background_detect_exec);
 }
 
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Playback with Talk Detection");
index df0c5392b6278e9e5fb4cbedc47f4fe2d3e26d53..e1452bb5905e57c7fcb5680358f9a43dc48f0e48 100644 (file)
@@ -36,23 +36,44 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/app.h"
 #include "asterisk/channel.h"
 
+/*** DOCUMENTATION
+       <application name="Transfer" language="en_US">
+               <synopsis>
+                       Transfer caller to remote extension.
+               </synopsis>
+               <syntax>
+                       <parameter name="dest" required="true" argsep="/">
+                               <argument name="Tech" />
+                               <argument name="destination" required="true" />
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Requests the remote caller be transferred
+                       to a given destination. If TECH (SIP, IAX2, LOCAL etc) is used, only
+                       an incoming call with the same channel technology will be transfered.
+                       Note that for SIP, if you transfer before call is setup, a 302 redirect
+                       SIP message will be returned to the caller.</para>
+                       <para>The result of the application will be reported in the <variable>TRANSFERSTATUS</variable>
+                       channel variable:</para>
+                       <variablelist>
+                               <variable name="TRANSFERSTATUS">
+                                       <value name="SUCCESS">
+                                               Transfer succeeded.
+                                       </value>
+                                       <value name="FAILURE">
+                                               Transfer failed.
+                                       </value>
+                                       <value name="UNSUPPORTED">
+                                               Transfer unsupported by channel driver.
+                                       </value>
+                               </variable>
+                       </variablelist>
+               </description>
+       </application>
+ ***/
 
 static const char *app = "Transfer";
 
-static const char *synopsis = "Transfer caller to remote extension";
-
-static const char *descrip = 
-"  Transfer([Tech/]dest):  Requests the remote caller be transferred\n"
-"to a given destination. If TECH (SIP, IAX2, LOCAL etc) is used, only\n"
-"an incoming call with the same channel technology will be transfered.\n"
-"Note that for SIP, if you transfer before call is setup, a 302 redirect\n"
-"SIP message will be returned to the caller.\n"
-"\nThe result of the application will be reported in the TRANSFERSTATUS\n"
-"channel variable:\n"
-"       SUCCESS      Transfer succeeded\n"
-"       FAILURE      Transfer failed\n"
-"       UNSUPPORTED  Transfer unsupported by channel driver\n";
-
 static int transfer_exec(struct ast_channel *chan, void *data)
 {
        int res;
@@ -115,7 +136,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       return ast_register_application(app, transfer_exec, synopsis, descrip);
+       return ast_register_application_xml(app, transfer_exec);
 }
 
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Transfers a caller to another extension");
index f71b32fd050d5736329f0f88af6bddead898a05b..e20159f5a153063e1b1a6caea75a80dc690d4d93 100644 (file)
@@ -34,24 +34,49 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/app.h"
 #include "asterisk/channel.h"
 
-static char *app = "SendURL";
-
-static char *synopsis = "Send a URL";
+/*** DOCUMENTATION
+       <application name="SendURL" language="en_US">
+               <synopsis>
+                       Send a URL.
+               </synopsis>
+               <syntax>
+                       <parameter name="URL" required="true" />
+                       <parameter name="option">
+                               <optionlist>
+                                       <option name="w">
+                                               <para>Execution will wait for an acknowledgement that the
+                                               URL has been loaded before continuing.</para>
+                                       </option>
+                               </optionlist>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Requests client go to <replaceable>URL</replaceable> (IAX2) or sends the
+                       URL to the client (other channels).</para>
+                       <para>Result is returned in the <variable>SENDURLSTATUS</variable> channel variable:</para>
+                       <variablelist>
+                               <variable name="SENDURLSTATUS">
+                                       <value name="SUCCESS">
+                                               URL successfully sent to client.
+                                       </value>
+                                       <value name="FAILURE">
+                                               Failed to send URL.
+                                       </value>
+                                       <value name="NOLOAD">
+                                               Client failed to load URL (wait enabled).
+                                       </value>
+                                       <value name="UNSUPPORTED">
+                                               Channel does not support URL transport.
+                                       </value>
+                               </variable>
+                       </variablelist>
+                       <para>SendURL continues normally if the URL was sent correctly or if the channel
+                       does not support HTML transport.  Otherwise, the channel is hung up.</para>
+               </description>
+       </application>
+ ***/
 
-static char *descrip = 
-"  SendURL(URL[,option]): Requests client go to URL (IAX2) or sends the \n"
-"URL to the client (other channels).\n"
-"Result is returned in the SENDURLSTATUS channel variable:\n"
-"    SUCCESS       URL successfully sent to client\n"
-"    FAILURE       Failed to send URL\n"
-"    NOLOAD        Client failed to load URL (wait enabled)\n"
-"    UNSUPPORTED   Channel does not support URL transport\n"
-"\n"
-"If the option 'w' is specified, execution will wait for an\n"
-"acknowledgement that the URL has been loaded before continuing\n"
-"\n"
-"SendURL continues normally if the URL was sent correctly or if the channel\n"
-"does not support HTML transport.  Otherwise, the channel is hung up.\n";
+static char *app = "SendURL";
 
 enum {
        OPTION_WAIT = (1 << 0),
@@ -143,7 +168,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       return ast_register_application(app, sendurl_exec, synopsis, descrip);
+       return ast_register_application_xml(app, sendurl_exec);
 }
 
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Send URL Applications");
index 91d067d541c75857f4a0acc7a9f94955c130e448..6d6354af6ae5e8753bc6dbd93e5a55c821ee778f 100644 (file)
@@ -30,21 +30,31 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/manager.h"
 #include "asterisk/app.h"
 
-static char *app = "UserEvent";
-
-static char *synopsis = "Send an arbitrary event to the manager interface";
-
-static char *descrip = 
-"  UserEvent(eventname[,body]): Sends an arbitrary event to the manager\n"
-"interface, with an optional body representing additional arguments.  The\n"
-"body may be specified as a | delimeted list of headers. Each additional\n"
-"argument will be placed on a new line in the event. The format of the\n"
-"event will be:\n"
-"    Event: UserEvent\n"
-"    UserEvent: <specified event name>\n"
-"    [body]\n"
-"If no body is specified, only Event and UserEvent headers will be present.\n";
+/*** DOCUMENTATION
+       <application name="UserEvent" language="en_US">
+               <synopsis>
+                       Send an arbitrary event to the manager interface.
+               </synopsis>
+               <syntax>
+                       <parameter name="eventname" required="true" />
+                       <parameter name="body" />
+               </syntax>
+               <description>
+                       <para>Sends an arbitrary event to the manager interface, with an optional
+                       <replaceable>body</replaceable> representing additional arguments. The
+                       <replaceable>body</replaceable> may be specified as
+                       a <literal>|</literal> delimeted list of headers. Each additional
+                       argument will be placed on a new line in the event. The format of the
+                       event will be:</para>
+                       <para>    Event: UserEvent</para>
+                       <para>    UserEvent: &lt;specified event name&gt;</para>
+                       <para>    [body]</para>
+                       <para>If no <replaceable>body</replaceable> is specified, only Event and UserEvent headers will be present.</para>
+               </description>
+       </application>
+ ***/
 
+static char *app = "UserEvent";
 
 static int userevent_exec(struct ast_channel *chan, void *data)
 {
@@ -83,7 +93,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       return ast_register_application(app, userevent_exec, synopsis, descrip);
+       return ast_register_application_xml(app, userevent_exec);
 }
 
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Custom User Event Application");
index 525cc1c55c59d66916a0081586b63e2636db21c3..b4c6a638499f15b3f49b815ac8aabc5c1e611e17 100644 (file)
@@ -33,16 +33,43 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/channel.h"
 
 static char *app_verbose = "Verbose";
-static char *verbose_synopsis = "Send arbitrary text to verbose output";
-static char *verbose_descrip =
-"Verbose([<level>,]<message>)\n"
-"  level must be an integer value.  If not specified, defaults to 0.\n";
-
 static char *app_log = "Log";
-static char *log_synopsis = "Send arbitrary text to a selected log level";
-static char *log_descrip =
-"Log(<level>,<message>)\n"
-"  level must be one of ERROR, WARNING, NOTICE, DEBUG, VERBOSE, DTMF\n";
+
+/*** DOCUMENTATION
+       <application name="Verbose" language="en_US">
+               <synopsis>
+                       Send arbitrary text to verbose output.
+               </synopsis>
+               <syntax>
+                       <parameter name="level">
+                               <para>Must be an integer value.  If not specified, defaults to 0.</para>
+                       </parameter>
+                       <parameter name="message" required="true">
+                               <para>Output text message.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Sends an arbitrary text message to verbose output.</para>
+               </description>
+       </application>
+       <application name="Log" language="en_US">
+               <synopsis>
+                       Send arbitrary text to a selected log level.
+               </synopsis>
+               <syntax>
+                       <parameter name="level">
+                               <para>Level must be one of <literal>ERROR</literal>, <literal>WARNING</literal>, <literal>NOTICE</literal>,
+                               <literal>DEBUG</literal>, <literal>VERBOSE</literal> or <literal>DTMF</literal>.</para> 
+                       </parameter>
+                       <parameter name="message" required="true">
+                               <para>Output text message.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Sends an arbitrary text message to a selected log level.</para>
+               </description>
+       </application>
+ ***/
 
 
 static int verbose_exec(struct ast_channel *chan, void *data)
@@ -149,8 +176,8 @@ static int load_module(void)
 {
        int res;
 
-       res = ast_register_application(app_log, log_exec, log_synopsis, log_descrip);
-       res |= ast_register_application(app_verbose, verbose_exec, verbose_synopsis, verbose_descrip);
+       res = ast_register_application_xml(app_log, log_exec);
+       res |= ast_register_application_xml(app_verbose, verbose_exec);
 
        return res;
 }
index 8b903b0ba4828d7ae77471ef6c4d3b91554344a4..0b6ccc677a12a4642b04d127c6cd2d6b9c7ed9c0 100644 (file)
@@ -34,15 +34,38 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/pbx.h"
 #include "asterisk/module.h"
 
+/*** DOCUMENTATION
+       <application name="WaitUntil" language="en_US">
+               <synopsis>
+                       Wait (sleep) until the current time is the given epoch.
+               </synopsis>
+               <syntax>
+                       <parameter name="epoch" required="true" />
+               </syntax>
+               <description>
+                       <para>Waits until the given <replaceable>epoch</replaceable>.</para>
+                       <para>Sets <variable>WAITUNTILSTATUS</variable> to one of the following values:</para>
+                       <variablelist>
+                               <variable name="WAITUNTILSTATUS">
+                                       <value name="OK">
+                                               Wait succeeded.
+                                       </value>
+                                       <value name="FAILURE">
+                                               Invalid argument.
+                                       </value>
+                                       <value name="HANGUP">
+                                               Channel hungup before time elapsed.
+                                       </value>
+                                       <value name="PAST">
+                                               Time specified had already past.
+                                       </value>
+                               </variable>
+                       </variablelist>
+               </description>
+       </application>
+ ***/
+
 static char *app = "WaitUntil";
-static char *synopsis = "Wait (sleep) until the current time is the given epoch";
-static char *descrip =
-"  WaitUntil(<epoch>): Waits until the given time.  Sets WAITUNTILSTATUS to\n"
-"one of the following values:\n"
-"  OK       Wait succeeded\n"
-"  FAILURE  Invalid argument\n"
-"  HANGUP   Channel hung up before time elapsed\n"
-"  PAST     The time specified was already past\n";
 
 static int waituntil_exec(struct ast_channel *chan, void *data)
 {
@@ -89,7 +112,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       return ast_register_application(app, waituntil_exec, synopsis, descrip);
+       return ast_register_application_xml(app, waituntil_exec);
 }
 
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Wait until specified time");
index 822458663a1342e046ebac8f20b68d34b9feb488..796244702cd39b36976a0aa035e4942d00c87a45 100644 (file)
@@ -33,29 +33,72 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/module.h"
 #include "asterisk/channel.h"
 
-static char *start_app = "While";
-static char *start_desc = 
-"  While(<expr>): Start a While Loop.  Execution will return to this\n"
-"point when EndWhile() is called until expr is no longer true.\n";
-
-static char *start_synopsis = "Start a while loop";
-
+/*** DOCUMENTATION
+       <application name="While" language="en_US">
+               <synopsis>
+                       Start a while loop.
+               </synopsis>
+               <syntax>
+                       <parameter name="expr" required="true" />
+               </syntax>
+               <description>
+                       <para>Start a While Loop.  Execution will return to this point when
+                       <literal>EndWhile()</literal> is called until expr is no longer true.</para>
+               </description>
+               <see-also>
+                       <ref type="application">EndWhile</ref>
+                       <ref type="application">ExitWhile</ref>
+                       <ref type="application">ContinueWhile</ref>
+               </see-also>
+       </application>
+       <application name="EndWhile" language="en_US">
+               <synopsis>
+                       End a while loop.
+               </synopsis>
+               <syntax />
+               <description>
+                       <para>Return to the previous called <literal>While()</literal>.</para>
+               </description>
+               <see-also>
+                       <ref type="application">While</ref>
+                       <ref type="application">ExitWhile</ref>
+                       <ref type="application">ContinueWhile</ref>
+               </see-also>
+       </application>
+       <application name="ExitWhile" language="en_US">
+               <synopsis>
+                       End a While loop.
+               </synopsis>
+               <syntax />
+               <description>
+                       <para>Exits a <literal>While()</literal> loop, whether or not the conditional has been satisfied.</para>
+               </description>
+               <see-also>
+                       <ref type="application">While</ref>
+                       <ref type="application">EndWhile</ref>
+                       <ref type="application">ContinueWhile</ref>
+               </see-also>
+       </application>
+       <application name="ContinueWhile" language="en_US">
+               <synopsis>
+                       Restart a While loop.
+               </synopsis>
+               <syntax />
+               <description>
+                       <para>Returns to the top of the while loop and re-evaluates the conditional.</para>
+               </description>
+               <see-also>
+                       <ref type="application">While</ref>
+                       <ref type="application">EndWhile</ref>
+                       <ref type="application">ExitWhile</ref>
+               </see-also>
+       </application>
+ ***/
 
+static char *start_app = "While";
 static char *stop_app = "EndWhile";
-static char *stop_desc = 
-"  EndWhile(): Return to the previous called While()\n";
-
-static char *stop_synopsis = "End a while loop";
-
 static char *exit_app = "ExitWhile";
-static char *exit_desc =
-"  ExitWhile(): Exits a While() loop, whether or not the conditional has been satisfied.\n";
-static char *exit_synopsis = "End a While loop";
-
 static char *continue_app = "ContinueWhile";
-static char *continue_desc =
-"  ContinueWhile(): Returns to the top of the while loop and re-evaluates the conditional.\n";
-static char *continue_synopsis = "Restart a While loop";
 
 #define VAR_SIZE 64
 
@@ -295,10 +338,10 @@ static int load_module(void)
 {
        int res;
 
-       res = ast_register_application(start_app, while_start_exec, start_synopsis, start_desc);
-       res |= ast_register_application(stop_app, while_end_exec, stop_synopsis, stop_desc);
-       res |= ast_register_application(exit_app, while_exit_exec, exit_synopsis, exit_desc);
-       res |= ast_register_application(continue_app, while_continue_exec, continue_synopsis, continue_desc);
+       res = ast_register_application_xml(start_app, while_start_exec);
+       res |= ast_register_application_xml(stop_app, while_end_exec);
+       res |= ast_register_application_xml(exit_app, while_exit_exec);
+       res |= ast_register_application_xml(continue_app, while_continue_exec);
 
        return res;
 }
index 2641e69b45afdec27203eea7547c35ab74da4d4d..bf9408090852bbe1e47e764ccef4dd3c28135bf8 100644 (file)
@@ -37,23 +37,42 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/translate.h"
 #include "asterisk/app.h"
 
-static char *app = "Zapateller";
-
-static char *synopsis = "Block telemarketers with SIT";
-
-static char *descrip = 
-"  Zapateller(options):  Generates special information tone to block\n"
-"telemarketers from calling you.  Options is a pipe-delimited list of\n" 
-"options.  The following options are available:\n"
-"    'answer'     - causes the line to be answered before playing the tone,\n" 
-"    'nocallerid' - causes Zapateller to only play the tone if there is no\n"
-"                   callerid information available.  Options should be\n"
-"                   separated by , characters\n\n"
-"  This application will set the following channel variable upon completion:\n"
-"    ZAPATELLERSTATUS - This will contain the last action accomplished by the\n"
-"                        Zapateller application. Possible values include:\n"
-"                        NOTHING | ANSWERED | ZAPPED\n\n";
+/*** DOCUMENTATION
+       <application name="Zapateller" language="en_US">
+               <synopsis>
+                       Block telemarketers with SIT.
+               </synopsis>
+               <syntax>
+                       <parameter name="options" required="true">
+                               <para>Comma delimited list of options.</para>
+                               <optionlist>
+                                       <option name="answer">
+                                               <para>Causes the line to be answered before playing the tone.</para>
+                                       </option>
+                                       <option name="nocallerid">
+                                               <para>Causes Zapateller to only play the tone if there is no
+                                               callerid information available.</para>
+                                       </option>
+                               </optionlist>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Generates special information tone to block telemarketers from calling you.</para>
+                       <para>This application will set the following channel variable upon completion:</para>
+                       <variablelist>
+                               <variable name="ZAPATELLERSTATUS">
+                                       <para>This will contain the last action accomplished by the
+                                       Zapateller application. Possible values include:</para>
+                                       <value name="NOTHING" />
+                                       <value name="ANSWERED" />
+                                       <value name="ZAPPED" />
+                               </variable>
+                       </variablelist>
+               </description>
+       </application>
+ ***/
 
+static char *app = "Zapateller";
 
 static int zapateller_exec(struct ast_channel *chan, void *data)
 {
@@ -107,7 +126,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
-       return ((ast_register_application(app, zapateller_exec, synopsis, descrip)) ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_SUCCESS);
+       return ((ast_register_application_xml(app, zapateller_exec)) ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_SUCCESS);
 }
 
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Block Telemarketers with Special Information Tone");
diff --git a/build_tools/get_documentation b/build_tools/get_documentation
new file mode 100644 (file)
index 0000000..7849c52
--- /dev/null
@@ -0,0 +1,3 @@
+/\/\*\*\* DOCUMENTATION/ {printit=1; next}
+/\*\*\*\// {if (printit) exit}
+// {if (printit) print}
index a87370380e3436913868734c0fbc6295e43a14a0..5abf42f153f4f19cd753c0a0322ecb63983bb3cd 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.ac Revision: 150731 .
+# From configure.ac Revision: 151252 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.61 for asterisk 1.6.
 #
@@ -800,6 +800,10 @@ LDAP_LIB
 LDAP_INCLUDE
 LDAP_DIR
 PBX_LDAP
+LIBXML2_LIB
+LIBXML2_INCLUDE
+LIBXML2_DIR
+PBX_LIBXML2
 LTDL_LIB
 LTDL_INCLUDE
 LTDL_DIR
@@ -970,6 +974,7 @@ AST_SHADOW_WARNINGS
 PBX_RTLD_NOLOAD
 PBX_IP_MTU_DISCOVER
 GSM_INTERNAL
+CONFIG_LIBXML2
 PBX_MISDN_FAC_RESULT
 PBX_MISDN_FAC_ERROR
 CONFIG_NETSNMP
@@ -1589,6 +1594,7 @@ Optional Features:
   --enable-dev-mode       Turn on developer mode
   --disable-largefile     omit support for large files
   --enable-internal-poll  Use Asterisk's poll implementation
+  --disable-xmldoc        Explicity disable XML documentation
 
 Optional Packages:
   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
@@ -1615,6 +1621,7 @@ Optional Packages:
   --with-isdnnet=PATH     use ISDN4Linux Library files in PATH
   --with-jack=PATH        use Jack Audio Connection Kit files in PATH
   --with-ldap=PATH        use OpenLDAP files in PATH
+  --with-libxml2=PATH     use LibXML2 files in PATH
   --with-ltdl=PATH        use libtool files in PATH
   --with-lua=PATH         use Lua files in PATH
   --with-misdn=PATH       use mISDN User Library files in PATH
@@ -8485,6 +8492,34 @@ fi
 
 
 
+    LIBXML2_DESCRIP="LibXML2"
+    LIBXML2_OPTION="libxml2"
+
+# Check whether --with-libxml2 was given.
+if test "${with_libxml2+set}" = set; then
+  withval=$with_libxml2;
+       case ${withval} in
+       n|no)
+       USE_LIBXML2=no
+       ;;
+       y|ye|yes)
+       ac_mandatory_list="${ac_mandatory_list} LIBXML2"
+       ;;
+       *)
+       LIBXML2_DIR="${withval}"
+       ac_mandatory_list="${ac_mandatory_list} LIBXML2"
+       ;;
+       esac
+
+fi
+
+    PBX_LIBXML2=0
+
+
+
+
+
+
     LTDL_DESCRIP="libtool"
     LTDL_OPTION="ltdl"
 
@@ -34444,6 +34479,212 @@ _ACEOF
 fi
 
 
+# Check whether --enable-xmldoc was given.
+if test "${enable_xmldoc+set}" = set; then
+  enableval=$enable_xmldoc; case "${enableval}" in
+               y|ye|yes) disable_xmldoc=no ;;
+               n|no)  disable_xmldoc=yes ;;
+               *) { { echo "$as_me:$LINENO: error: bad value ${enableval} for --disable-xmldoc" >&5
+echo "$as_me: error: bad value ${enableval} for --disable-xmldoc" >&2;}
+   { (exit 1); exit 1; }; }  ;;
+       esac
+else
+  disable_xmldoc=no
+fi
+
+
+if test "${disable_xmldoc}" != "yes"; then
+
+    if test "x${PBX_LIBXML2}" != "x1" -a "${USE_LIBXML2}" != "no"; then
+       PBX_LIBXML2=0
+       if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}xml2-config", so it can be a program name with args.
+set dummy ${ac_tool_prefix}xml2-config; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CONFIG_LIBXML2+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CONFIG_LIBXML2"; then
+  ac_cv_prog_CONFIG_LIBXML2="$CONFIG_LIBXML2" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CONFIG_LIBXML2="${ac_tool_prefix}xml2-config"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CONFIG_LIBXML2=$ac_cv_prog_CONFIG_LIBXML2
+if test -n "$CONFIG_LIBXML2"; then
+  { echo "$as_me:$LINENO: result: $CONFIG_LIBXML2" >&5
+echo "${ECHO_T}$CONFIG_LIBXML2" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CONFIG_LIBXML2"; then
+  ac_ct_CONFIG_LIBXML2=$CONFIG_LIBXML2
+  # Extract the first word of "xml2-config", so it can be a program name with args.
+set dummy xml2-config; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CONFIG_LIBXML2+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CONFIG_LIBXML2"; then
+  ac_cv_prog_ac_ct_CONFIG_LIBXML2="$ac_ct_CONFIG_LIBXML2" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CONFIG_LIBXML2="xml2-config"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CONFIG_LIBXML2=$ac_cv_prog_ac_ct_CONFIG_LIBXML2
+if test -n "$ac_ct_CONFIG_LIBXML2"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_CONFIG_LIBXML2" >&5
+echo "${ECHO_T}$ac_ct_CONFIG_LIBXML2" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  if test "x$ac_ct_CONFIG_LIBXML2" = x; then
+    CONFIG_LIBXML2="No"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    CONFIG_LIBXML2=$ac_ct_CONFIG_LIBXML2
+  fi
+else
+  CONFIG_LIBXML2="$ac_cv_prog_CONFIG_LIBXML2"
+fi
+
+       if test ! "x${CONFIG_LIBXML2}" = xNo; then
+           if test x"" = x ; then A=--cflags ; else A="" ; fi
+           LIBXML2_INCLUDE=$(${CONFIG_LIBXML2} $A)
+           if test x"" = x ; then A=--libs ; else A="" ; fi
+           LIBXML2_LIB=$(${CONFIG_LIBXML2} $A)
+           if test x"#include <libxml/tree.h>
+       #include <libxml/parser.h>" != x ; then
+               saved_cppflags="${CPPFLAGS}"
+               if test "x${LIBXML2_DIR}" != "x"; then
+                   LIBXML2_INCLUDE="-I${LIBXML2_DIR}/include"
+               fi
+               CPPFLAGS="${CPPFLAGS} ${LIBXML2_INCLUDE}"
+
+               saved_ldflags="${LDFLAGS}"
+               LDFLAGS="${LIBXML2_LIB}"
+
+               cat >conftest.$ac_ext <<_ACEOF
+ /* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+ #include <libxml/tree.h>
+       #include <libxml/parser.h>
+int
+main ()
+{
+ LIBXML_TEST_VERSION;
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+     PBX_LIBXML2=1
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LIBXML2 1
+_ACEOF
+
+
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+               CPPFLAGS="${saved_cppflags}"
+               LDFLAGS="${saved_ldflags}"
+           else
+               PBX_LIBXML2=1
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LIBXML2 1
+_ACEOF
+
+           fi
+       fi
+    fi
+
+       if test "${PBX_LIBXML2}" != 1; then
+               { echo "$as_me:$LINENO: *** XML documentation will not be available because the 'libxml2' development package is missing." >&5
+echo "$as_me: *** XML documentation will not be available because the 'libxml2' development package is missing." >&6;}
+               { echo "$as_me:$LINENO: *** Please run the 'configure' script with the '--disable-xmldoc' parameter option" >&5
+echo "$as_me: *** Please run the 'configure' script with the '--disable-xmldoc' parameter option" >&6;}
+               { echo "$as_me:$LINENO: *** or install the 'libxml2' development package." >&5
+echo "$as_me: *** or install the 'libxml2' development package." >&6;}
+               exit 1
+       fi
+fi
+
 
 if test "x${PBX_MISDN}" != "x1" -a "${USE_MISDN}" != "no"; then
    pbxlibdir=""
@@ -51281,6 +51522,10 @@ LDAP_LIB!$LDAP_LIB$ac_delim
 LDAP_INCLUDE!$LDAP_INCLUDE$ac_delim
 LDAP_DIR!$LDAP_DIR$ac_delim
 PBX_LDAP!$PBX_LDAP$ac_delim
+LIBXML2_LIB!$LIBXML2_LIB$ac_delim
+LIBXML2_INCLUDE!$LIBXML2_INCLUDE$ac_delim
+LIBXML2_DIR!$LIBXML2_DIR$ac_delim
+PBX_LIBXML2!$PBX_LIBXML2$ac_delim
 LTDL_LIB!$LTDL_LIB$ac_delim
 LTDL_INCLUDE!$LTDL_INCLUDE$ac_delim
 LTDL_DIR!$LTDL_DIR$ac_delim
@@ -51290,10 +51535,6 @@ LUA_INCLUDE!$LUA_INCLUDE$ac_delim
 LUA_DIR!$LUA_DIR$ac_delim
 PBX_LUA!$PBX_LUA$ac_delim
 MISDN_LIB!$MISDN_LIB$ac_delim
-MISDN_INCLUDE!$MISDN_INCLUDE$ac_delim
-MISDN_DIR!$MISDN_DIR$ac_delim
-PBX_MISDN!$PBX_MISDN$ac_delim
-NBS_LIB!$NBS_LIB$ac_delim
 _ACEOF
 
   if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then
@@ -51335,6 +51576,10 @@ _ACEOF
 ac_delim='%!_!# '
 for ac_last_try in false false false false false :; do
   cat >conf$$subs.sed <<_ACEOF
+MISDN_INCLUDE!$MISDN_INCLUDE$ac_delim
+MISDN_DIR!$MISDN_DIR$ac_delim
+PBX_MISDN!$PBX_MISDN$ac_delim
+NBS_LIB!$NBS_LIB$ac_delim
 NBS_INCLUDE!$NBS_INCLUDE$ac_delim
 NBS_DIR!$NBS_DIR$ac_delim
 PBX_NBS!$PBX_NBS$ac_delim
@@ -51428,10 +51673,6 @@ SQLITE_DIR!$SQLITE_DIR$ac_delim
 PBX_SQLITE!$PBX_SQLITE$ac_delim
 SQLITE3_LIB!$SQLITE3_LIB$ac_delim
 SQLITE3_INCLUDE!$SQLITE3_INCLUDE$ac_delim
-SQLITE3_DIR!$SQLITE3_DIR$ac_delim
-PBX_SQLITE3!$PBX_SQLITE3$ac_delim
-SUPPSERV_LIB!$SUPPSERV_LIB$ac_delim
-SUPPSERV_INCLUDE!$SUPPSERV_INCLUDE$ac_delim
 _ACEOF
 
   if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then
@@ -51473,6 +51714,10 @@ _ACEOF
 ac_delim='%!_!# '
 for ac_last_try in false false false false false :; do
   cat >conf$$subs.sed <<_ACEOF
+SQLITE3_DIR!$SQLITE3_DIR$ac_delim
+PBX_SQLITE3!$PBX_SQLITE3$ac_delim
+SUPPSERV_LIB!$SUPPSERV_LIB$ac_delim
+SUPPSERV_INCLUDE!$SUPPSERV_INCLUDE$ac_delim
 SUPPSERV_DIR!$SUPPSERV_DIR$ac_delim
 PBX_SUPPSERV!$PBX_SUPPSERV$ac_delim
 OPENSSL_LIB!$OPENSSL_LIB$ac_delim
@@ -51533,6 +51778,7 @@ AST_SHADOW_WARNINGS!$AST_SHADOW_WARNINGS$ac_delim
 PBX_RTLD_NOLOAD!$PBX_RTLD_NOLOAD$ac_delim
 PBX_IP_MTU_DISCOVER!$PBX_IP_MTU_DISCOVER$ac_delim
 GSM_INTERNAL!$GSM_INTERNAL$ac_delim
+CONFIG_LIBXML2!$CONFIG_LIBXML2$ac_delim
 PBX_MISDN_FAC_RESULT!$PBX_MISDN_FAC_RESULT$ac_delim
 PBX_MISDN_FAC_ERROR!$PBX_MISDN_FAC_ERROR$ac_delim
 CONFIG_NETSNMP!$CONFIG_NETSNMP$ac_delim
@@ -51563,7 +51809,7 @@ CURL_CONFIG!$CURL_CONFIG$ac_delim
 LTLIBOBJS!$LTLIBOBJS$ac_delim
 _ACEOF
 
-  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 88; then
+  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 93; then
     break
   elif $ac_last_try; then
     { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
index 1f09738427c8312133f4df50a2cd86e582f8a025..6c69ce63ec92c51ecae5610e59ba73a5286b67c9 100644 (file)
@@ -236,6 +236,7 @@ AST_EXT_LIB_SETUP([IODBC], [iODBC], [iodbc])
 AST_EXT_LIB_SETUP([ISDNNET], [ISDN4Linux Library], [isdnnet])
 AST_EXT_LIB_SETUP([JACK], [Jack Audio Connection Kit], [jack])
 AST_EXT_LIB_SETUP([LDAP], [OpenLDAP], [ldap])
+AST_EXT_LIB_SETUP([LIBXML2], [LibXML2], [libxml2])
 AST_EXT_LIB_SETUP([LTDL], [libtool], [ltdl])
 AST_EXT_LIB_SETUP([LUA], [Lua], [lua])
 AST_EXT_LIB_SETUP([MISDN], [mISDN User Library], [misdn])
@@ -1248,6 +1249,28 @@ AST_EXT_LIB_CHECK([LTDL], [ltdl], [lt_dlinit], [ltdl.h], [])
 
 AST_EXT_LIB_CHECK([LDAP], [ldap], [ldap_initialize], [ldap.h])
 
+AC_ARG_ENABLE([xmldoc],
+       [AS_HELP_STRING([--disable-xmldoc],
+               [Explicity disable XML documentation])],
+       [case "${enableval}" in
+               y|ye|yes) disable_xmldoc=no ;;
+               n|no)  disable_xmldoc=yes ;;
+               *) AC_MSG_ERROR(bad value ${enableval} for --disable-xmldoc)  ;;
+       esac], [disable_xmldoc=no])
+
+if test "${disable_xmldoc}" != "yes"; then
+       AST_EXT_TOOL_CHECK([LIBXML2], [xml2], , ,
+       [#include <libxml/tree.h>
+       #include <libxml/parser.h>],
+       [LIBXML_TEST_VERSION])
+       if test "${PBX_LIBXML2}" != 1; then
+               AC_MSG_NOTICE(*** XML documentation will not be available because the 'libxml2' development package is missing.)
+               AC_MSG_NOTICE(*** Please run the 'configure' script with the '--disable-xmldoc' parameter option)
+               AC_MSG_NOTICE(*** or install the 'libxml2' development package.)
+               exit 1
+       fi
+fi
+
 AST_EXT_LIB_CHECK([MISDN], [mISDN], [mISDN_open], [mISDNuser/mISDNlib.h])
 
 if test "${PBX_MISDN}" = 1; then
diff --git a/doc/appdocsxml.dtd b/doc/appdocsxml.dtd
new file mode 100644 (file)
index 0000000..67e86d6
--- /dev/null
@@ -0,0 +1,64 @@
+  <!ELEMENT docs (application|function)* >
+
+  <!ELEMENT application (synopsis?,syntax?,description?,see-also?)>
+  <!ATTLIST application name CDATA #REQUIRED>
+  <!ATTLIST application language CDATA #REQUIRED>
+
+  <!ELEMENT function (synopsis?,syntax?,description?,see-also?)>
+  <!ATTLIST function name CDATA #REQUIRED>
+  <!ATTLIST function language CDATA #REQUIRED>  
+
+  <!ELEMENT see-also (ref*)>
+
+  <!ELEMENT ref (#PCDATA)*>
+  <!ATTLIST ref type (application|function|astcli|link|manpage) #REQUIRED>
+
+  <!ELEMENT synopsis (#PCDATA)>
+  
+  <!ELEMENT syntax (parameter*)>
+  <!ATTLIST syntax argsep CDATA ",">
+
+  <!ELEMENT description (para|note|warning|variablelist|enumlist)*>
+
+  <!ELEMENT parameter (optionlist|enumlist|argument|para|note|warning)*>
+  <!ATTLIST parameter name CDATA #REQUIRED>
+  <!ATTLIST parameter required (yes|no|true|false) "false">
+  <!ATTLIST parameter multiple (yes|no|true|false) "false">
+  <!ATTLIST parameter hasparams (yes|no|true|false|optional) "false">
+  <!ATTLIST parameter argsep CDATA ",">
+
+  <!ELEMENT optionlist (option+)>
+  <!ELEMENT option (argument|para|note|warning|variablelist|enumlist)*>
+  <!ATTLIST option name CDATA #REQUIRED> 
+  <!ATTLIST option argsep CDATA ",">
+  <!ATTLIST option implies CDATA "">
+
+  <!ELEMENT enumlist (enum+)>
+  <!ELEMENT enum (para|note|warning)*>
+  <!ATTLIST enum name CDATA #REQUIRED>
+
+  <!ELEMENT argument (para|note|warning|variablelist|argument)*>
+  <!ATTLIST argument name CDATA #REQUIRED>
+  <!ATTLIST argument multiple (yes|no|true|false) "false">
+  <!ATTLIST argument required (yes|no|true|false) "false">
+  <!ATTLIST argument hasparams (yes|no|true|false|optional) "false">
+
+  <!ELEMENT para (#PCDATA|astcli|literal|emphasis|filename|directory|replaceable|variable)*>
+  <!ELEMENT literal (#PCDATA)>
+  <!ELEMENT emphasis (#PCDATA)>
+  <!ELEMENT filename (#PCDATA)>
+  <!ELEMENT replaceable (#PCDATA)>
+  <!ELEMENT directory (#PCDATA)>
+  <!ELEMENT astcli (#PCDATA)>
+  <!ELEMENT note (para+)>
+  <!ELEMENT warning (para+)>
+  <!ELEMENT variablelist (variable+)>
+  <!ELEMENT variable (#PCDATA|value|para)*>
+  <!ATTLIST variable name CDATA "">
+  
+  <!ELEMENT value (#PCDATA)>
+  <!ATTLIST value name CDATA #REQUIRED>
+  <!ATTLIST value default CDATA "">
+
index f39d4dc05a81fa6978b5680b69520fdebdef3b4a..4b08023a6295c6422c8bfa820b58fccc59677b6d 100644 (file)
@@ -82,6 +82,9 @@ rungroup = asterisk
 ; Enable internal timing support (-I)
 internal_timing = yes | no
 
+; Language Options
+documentation_language = en | es | ru
+
 ; These options have no command line equivalent
 
 ; Cache record() files in another directory until completion
index 0849e95396a61f7826dde30464237a35c7e9d2fa..28805b9432fa5663a2fb694b254c41f654c53829 100644 (file)
@@ -30,6 +30,35 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/pbx.h"      /* function register/unregister */
 #include "asterisk/utils.h"
 
+/*** DOCUMENTATION
+       <function name="BASE64_ENCODE" language="en_US">
+               <synopsis>
+                       Encode a string in base64.
+               </synopsis>
+               <syntax>
+                       <parameter name="string" required="true">
+                               <para>Input string</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Returns the base64 string.</para>
+               </description>
+       </function>
+       <function name="BASE64_DECODE" language="en_US">
+               <synopsis>
+                       Decode a base64 string.
+               </synopsis>
+               <syntax>
+                       <parameter name="string" required="true">
+                               <para>Input string.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Returns the plain text string.</para>
+               </description>
+       </function>
+ ***/
+
 static int base64_encode(struct ast_channel *chan, const char *cmd, char *data,
                         char *buf, size_t len)
 {
@@ -58,17 +87,11 @@ static int base64_decode(struct ast_channel *chan, const char *cmd, char *data,
 
 static struct ast_custom_function base64_encode_function = {
        .name = "BASE64_ENCODE",
-       .synopsis = "Encode a string in base64",
-       .desc = "Returns the base64 string\n",
-       .syntax = "BASE64_ENCODE(<string>)",
        .read = base64_encode,
 };
 
 static struct ast_custom_function base64_decode_function = {
        .name = "BASE64_DECODE",
-       .synopsis = "Decode a base64 string",
-       .desc = "Returns the plain text string\n",
-       .syntax = "BASE64_DECODE(<base64_string>)",
        .read = base64_decode,
 };
 
index 2a2fa78c798355b07afe53fa2843ed39f875a59d..c353b20fd71ce9093050775d9dbc962542b438b3 100644 (file)
@@ -35,6 +35,20 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/channel.h"
 #include "asterisk/astdb.h"
 
+/*** DOCUMENTATION
+       <function name="BLACKLIST" language="en_US">
+               <synopsis>
+                       Check if the callerid is on the blacklist.
+               </synopsis>
+               <syntax />
+               <description>
+                       <para>Uses astdb to check if the Caller*ID is in family <literal>blacklist</literal>.
+                       Returns <literal>1</literal> or <literal>0</literal>.</para>
+               </description>
+       </function>
+
+***/
+
 static int blacklist_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 {
        char blacklist[1];
@@ -55,9 +69,6 @@ static int blacklist_read(struct ast_channel *chan, const char *cmd, char *data,
 
 static struct ast_custom_function blacklist_function = {
        .name = "BLACKLIST",
-       .synopsis = "Check if the callerid is on the blacklist",
-       .desc = "Uses astdb to check if the Caller*ID is in family 'blacklist'.  Returns 1 or 0.\n",
-       .syntax = "BLACKLIST()",
        .read = blacklist_read,
 };
 
index c56089ca298c482ad332fcbad5721f77935fb6eb..7f066cdaad4e6fced13911abe462e3b8c0dc4f34 100644 (file)
@@ -32,6 +32,74 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/app.h"
 #include "asterisk/callerid.h"
 
+/*** DOCUMENTATION
+       <function name="CALLERID" language="en_US">
+               <synopsis>
+                       Gets or sets Caller*ID data on the channel.
+               </synopsis>
+               <syntax>
+                       <parameter name="datatype" required="true">
+                               <para>The allowable datatypes are:</para>
+                               <enumlist>
+                                       <enum name="all" />
+                                       <enum name="num" />
+                                       <enum name="ANI" />
+                                       <enum name="DNID" />
+                                       <enum name="RDNIS" />
+                                       <enum name="pres" />
+                                       <enum name="ton" />
+                               </enumlist>
+                       </parameter>
+                       <parameter name="CID">
+                               <para>Optional Caller*ID</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Gets or sets Caller*ID data on the channel. Uses channel callerid by default or optional
+                       callerid, if specified.</para>
+               </description>
+       </function>
+       <function name="CALLERPRES" language="en_US">
+               <synopsis>
+                       Gets or sets Caller*ID presentation on the channel.
+               </synopsis>
+               <syntax />
+               <description>
+                       <para>Gets or sets Caller*ID presentation on the channel. The following values
+                       are valid:</para>
+                       <enumlist>
+                               <enum name="allowed_not_screened">
+                                       <para>Presentation Allowed, Not Screened.</para>
+                               </enum>
+                               <enum name="allowed_passed_screen">
+                                       <para>Presentation Allowed, Passed Screen.</para>
+                               </enum>
+                               <enum name="allowed_failed_screen">
+                                       <para>Presentation Allowed, Failed Screen.</para>
+                               </enum>
+                               <enum name="allowed">
+                                       <para>Presentation Allowed, Network Number.</para>
+                               </enum>
+                               <enum name="prohib_not_screened">
+                                       <para>Presentation Prohibited, Not Screened.</para>
+                               </enum>
+                               <enum name="prohib_passed_screen">
+                                       <para>Presentation Prohibited, Passed Screen.</para>
+                               </enum>
+                               <enum name="prohib_failed_screen">
+                                       <para>Presentation Prohibited, Failed Screen.</para>
+                               </enum>
+                               <enum name="prohib">
+                                       <para>Presentation Prohibited, Network Number.</para>
+                               </enum>
+                               <enum name="unavailable">
+                                       <para>Number Unavailable.</para>
+                               </enum>
+                       </enumlist>
+               </description>
+       </function>
+ ***/
+
 static int callerpres_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 {
        ast_copy_string(buf, ast_named_caller_presentation(chan->cid.cid_pres), len);
@@ -184,33 +252,12 @@ static int callerid_write(struct ast_channel *chan, const char *cmd, char *data,
 
 static struct ast_custom_function callerid_function = {
        .name = "CALLERID",
-       .synopsis = "Gets or sets Caller*ID data on the channel.",
-       .syntax = "CALLERID(datatype[,<optional-CID>])",
-       .desc =
-               "Gets or sets Caller*ID data on the channel.  The allowable datatypes\n"
-               "are \"all\", \"name\", \"num\", \"ANI\", \"DNID\", \"RDNIS\", \"pres\",\n"
-               "and \"ton\".\n"
-               "Uses channel callerid by default or optional callerid, if specified.\n",
        .read = callerid_read,
        .write = callerid_write,
 };
 
 static struct ast_custom_function callerpres_function = {
        .name = "CALLERPRES",
-       .synopsis = "Gets or sets Caller*ID presentation on the channel.",
-       .syntax = "CALLERPRES()",
-       .desc =
-"Gets or sets Caller*ID presentation on the channel.  The following values\n"
-"are valid:\n"
-"      allowed_not_screened    : Presentation Allowed, Not Screened\n"
-"      allowed_passed_screen   : Presentation Allowed, Passed Screen\n" 
-"      allowed_failed_screen   : Presentation Allowed, Failed Screen\n" 
-"      allowed                 : Presentation Allowed, Network Number\n"
-"      prohib_not_screened     : Presentation Prohibited, Not Screened\n" 
-"      prohib_passed_screen    : Presentation Prohibited, Passed Screen\n"
-"      prohib_failed_screen    : Presentation Prohibited, Failed Screen\n"
-"      prohib                  : Presentation Prohibited, Network Number\n"
-"      unavailable             : Number Unavailable\n",
        .read = callerpres_read,
        .write = callerpres_write,
 };
index 9b73d03f18ed70fea30bca41665377e6d7530df8..6c80e4f93175a9420027f214dc63e766bf9fb9fc 100644 (file)
@@ -36,6 +36,133 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/app.h"
 #include "asterisk/cdr.h"
 
+/*** DOCUMENTATION
+       <function name="CDR" language="en_US">
+               <synopsis>
+                       Gets or sets a CDR variable.
+               </synopsis>     
+               <syntax>
+                       <parameter name="name" required="true">
+                               <para>CDR field name:</para>
+                               <enumlist>
+                                       <enum name="clid">
+                                               <para>Caller ID.</para>
+                                       </enum>
+                                       <enum name="lastdata">
+                                               <para>Last application arguments.</para>
+                                       </enum>
+                                       <enum name="disposition">
+                                               <para>ANSWERED, NO ANSWER, BUSY.</para>
+                                       </enum>
+                                       <enum name="src">
+                                               <para>Source.</para>
+                                       </enum>
+                                       <enum name="start">
+                                               <para>Time the call started.</para>
+                                       </enum>
+                                       <enum name="amaflags">
+                                               <para>DOCUMENTATION, BILL, IGNORE, etc.</para>
+                                       </enum>
+                                       <enum name="dst">
+                                               <para>Destination.</para>
+                                       </enum>
+                                       <enum name="answer">
+                                               <para>Time the call was answered.</para>
+                                       </enum>
+                                       <enum name="accountcode">
+                                               <para>The channel's account code.</para>
+                                       </enum>
+                                       <enum name="dcontext">
+                                               <para>Destination context.</para>
+                                       </enum>
+                                       <enum name="end">
+                                               <para>Time the call ended.</para>
+                                       </enum>
+                                       <enum name="uniqueid">
+                                               <para>The channel's unique id.</para>
+                                       </enum>
+                                       <enum name="dstchannel">
+                                               <para>Destination channel.</para>
+                                       </enum>
+                                       <enum name="duration">
+                                               <para>Duration of the call.</para>
+                                       </enum>
+                                       <enum name="userfield">
+                                               <para>The channel's user specified field.</para>
+                                       </enum>
+                                       <enum name="lastapp">
+                                               <para>Last application.</para>
+                                       </enum>
+                                       <enum name="billsec">
+                                               <para>Duration of the call once it was answered.</para>
+                                       </enum>
+                                       <enum name="channel">
+                                               <para>Channel name.</para>
+                                       </enum>
+                               </enumlist>
+                       </parameter>
+                       <parameter name="options" required="false">
+                               <optionlist>
+                                       <option name="l">
+                                               <para>Uses the most recent CDR on a channel with multiple records</para>
+                                       </option>
+                                       <option name="r">
+                                               <para>Searches the entire stack of CDRs on the channel.</para>
+                                       </option>
+                                       <option name="s">
+                                               <para>Skips any CDR's that are marked 'LOCKED' due to forkCDR() calls.
+                                               (on setting/writing CDR vars only)</para>
+                                       </option>
+                                       <option name="u">
+                                               <para>Retrieves the raw, unprocessed value.</para>
+                                               <para>For example, 'start', 'answer', and 'end' will be retrieved as epoch
+                                               values, when the <literal>u</literal> option is passed, but formatted as YYYY-MM-DD HH:MM:SS
+                                               otherwise.  Similarly, disposition and amaflags will return their raw
+                                               integral values.</para>
+                                       </option>
+                               </optionlist>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>All of the CDR field names are read-only, except for <literal>accountcode</literal>,
+                       <literal>userfield</literal>, and <literal>amaflags</literal>. You may, however, supply
+                       a name not on the above list, and create your own variable, whose value can be changed
+                       with this function, and this variable will be stored on the cdr.</para>
+                       <note><para>For setting CDR values, the <literal>l</literal> flag does not apply to
+                       setting the <literal>accountcode</literal>, <literal>userfield</literal>, or
+                       <literal>amaflags</literal>.</para></note>
+                       <para>Raw values for <literal>disposition</literal>:</para>
+                       <enumlist>
+                               <enum name="1">
+                                       <para>NO ANSWER</para>
+                               </enum>
+                               <enum name="2">
+                                       <para>BUSY</para>
+                               </enum>
+                               <enum name="3">
+                                       <para>FAILED</para>
+                               </enum>
+                               <enum name="4">
+                                       <para>ANSWERED</para>
+                               </enum>
+                       </enumlist>
+                       <para>Raw values for <literal>amaflags</literal>:</para>
+                       <enumlist>
+                               <enum name="1">
+                                       <para>OMIT</para>
+                               </enum>
+                               <enum name="2">
+                                       <para>BILLING</para>
+                               </enum>
+                               <enum name="3">
+                                       <para>DOCUMENTATION</para>
+                               </enum>
+                       </enumlist>
+                       <para>Example: exten => 1,1,Set(CDR(userfield)=test)</para>
+               </description>
+       </function>
+ ***/
+
 enum {
        OPT_RECURSIVE = (1 << 0),
        OPT_UNPARSED = (1 << 1),
@@ -128,44 +255,8 @@ static int cdr_write(struct ast_channel *chan, const char *cmd, char *parse,
 
 static struct ast_custom_function cdr_function = {
        .name = "CDR",
-       .synopsis = "Gets or sets a CDR variable",
-       .syntax = "CDR(<name>[,options])",
        .read = cdr_read,
        .write = cdr_write,
-       .desc =
-"Options:\n"
-"  'l' uses the most recent CDR on a channel with multiple records\n"
-"  'r' searches the entire stack of CDRs on the channel\n"
-"  's' skips any CDR's that are marked 'LOCKED' due to forkCDR() calls.\n"
-"      (on setting/writing CDR vars only)\n"
-"  'u' retrieves the raw, unprocessed value\n"
-"  For example, 'start', 'answer', and 'end' will be retrieved as epoch\n"
-"  values, when the 'u' option is passed, but formatted as YYYY-MM-DD HH:MM:SS\n"
-"  otherwise.  Similarly, disposition and amaflags will return their raw\n"
-"  integral values.\n"
-"  Here is a list of all the available cdr field names:\n"
-"    clid          lastdata       disposition\n"
-"    src           start          amaflags\n"
-"    dst           answer         accountcode\n"
-"    dcontext      end            uniqueid\n"
-"    dstchannel    duration       userfield\n"
-"    lastapp       billsec        channel\n"
-"  All of the above variables are read-only, except for accountcode,\n"
-"  userfield, and amaflags. You may, however,  supply\n"
-"  a name not on the above list, and create your own\n"
-"  variable, whose value can be changed with this function,\n"
-"  and this variable will be stored on the cdr.\n"
-"  For setting CDR values, the 'l' flag does not apply to\n"
-"  setting the accountcode, userfield, or amaflags.\n"
-"   raw values for disposition:\n"
-"       1 = NO ANSWER\n"
-"       2 = BUSY\n"
-"       3 = FAILED\n"
-"       4 = ANSWERED\n"
-"    raw values for amaflags:\n"
-"       1 = OMIT\n"
-"       2 = BILLING\n"
-"       3 = DOCUMENTATION\n",
 };
 
 static int unload_module(void)
index c13c668a306598fa0080d51833ca47f12fc1476b..4393c2e337651ce357482ddcd76b388111c4d864 100644 (file)
@@ -38,6 +38,168 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/indications.h"
 #include "asterisk/stringfields.h"
 
+/*** DOCUMENTATION
+       <function name="CHANNELS" language="en_US">
+               <synopsis>
+                       Gets the list of channels, optionally filtering by a regular expression.
+               </synopsis>
+               <syntax>
+                       <parameter name="regular_expression" />
+               </syntax>
+               <description>
+                       <para>Gets the list of channels, optionally filtering by a <replaceable>regular_expression</replaceable>. If
+                       no argument is provided, all known channels are returned. The
+                       <replaceable>regular_expression</replaceable> must correspond to
+                       the POSIX.2 specification, as shown in <emphasis>regex(7)</emphasis>. The list returned
+                       will be space-delimited.</para>
+               </description>
+       </function>
+       <function name="CHANNEL" language="en_US">
+               <synopsis>
+                       Gets/sets various pieces of information about the channel.
+               </synopsis>
+               <syntax>
+                       <parameter name="item" required="true">
+                               <para>Standard items (provided by all channel technologies) are:</para>
+                               <enumlist>
+                                       <enum name="audioreadformat">
+                                               <para>R/O format currently being read.</para>
+                                       </enum>
+                                       <enum name="audionativeformat">
+                                               <para>R/O format used natively for audio.</para>
+                                       </enum>
+                                       <enum name="audiowriteformat">
+                                               <para>R/O format currently being written.</para>
+                                       </enum>
+                                       <enum name="callgroup">
+                                               <para>R/W call groups for call pickup.</para>
+                                       </enum>
+                                       <enum name="channeltype">
+                                               <para>R/O technology used for channel.</para>
+                                       </enum>
+                                       <enum name="language">
+                                               <para>R/W language for sounds played.</para>
+                                       </enum>
+                                       <enum name="musicclass">
+                                               <para>R/W class (from musiconhold.conf) for hold music.</para>
+                                       </enum>
+                                       <enum name="parkinglot">
+                                               <para>R/W parkinglot for parking.</para>
+                                       </enum>
+                                       <enum name="rxgain">
+                                               <para>R/W set rxgain level on channel drivers that support it.</para>
+                                       </enum>
+                                       <enum name="state">
+                                               <para>R/O state for channel</para>
+                                       </enum>
+                                       <enum name="tonezone">
+                                               <para>R/W zone for indications played</para>
+                                       </enum>
+                                       <enum name="txgain">
+                                               <para>R/W set txgain level on channel drivers that support it.</para>
+                                       </enum>
+                                       <enum name="videonativeformat">
+                                               <para>R/O format used natively for video</para>
+                                       </enum>
+                                       <enum name="trace">
+                                               <para>R/W whether or not context tracing is enabled, only available
+                                               <emphasis>if CHANNEL_TRACE is defined</emphasis>.</para>
+                                       </enum>
+                               </enumlist>
+                               <para><emphasis>chan_sip</emphasis> provides the following additional options:</para>
+                               <enumlist>
+                                       <enum name="peerip">
+                                               <para>R/O Get the IP address of the peer.</para>
+                                       </enum>
+                                       <enum name="recvip">
+                                               <para>R/O Get the source IP address of the peer.</para>
+                                       </enum>
+                                       <enum name="from">
+                                               <para>R/O Get the URI from the From: header.</para>
+                                       </enum>
+                                       <enum name="uri">
+                                               <para>R/O Get the URI from the Contact: header.</para>
+                                       </enum>
+                                       <enum name="useragent">
+                                               <para>R/O Get the useragent.</para>
+                                       </enum>
+                                       <enum name="peername">
+                                               <para>R/O Get the name of the peer.</para>
+                                       </enum>
+                                       <enum name="t38passthrough">
+                                               <para>R/O <literal>1</literal> if T38 is offered or enabled in this channel,
+                                               otherwise <literal>0</literal></para>
+                                       </enum>
+                                       <enum name="rtpqos">
+                                               <para>R/O Get QOS information about the RTP stream</para>
+                                               <para>    This option takes two additional arguments:</para>
+                                               <para>    Argument 1:</para>
+                                               <para>     <literal>audio</literal>             Get data about the audio stream</para>
+                                               <para>     <literal>video</literal>             Get data about the video stream</para>
+                                               <para>     <literal>text</literal>              Get data about the text stream</para>
+                                               <para>    Argument 2:</para>
+                                               <para>     <literal>local_ssrc</literal>        Local SSRC (stream ID)</para>
+                                               <para>     <literal>local_lostpackets</literal> Local lost packets</para>
+                                               <para>     <literal>local_jitter</literal>      Local calculated jitter</para>
+                                               <para>     <literal>local_maxjitter</literal>   Local calculated jitter (maximum)</para>
+                                               <para>     <literal>local_minjitter</literal>   Local calculated jitter (minimum)</para>
+                                               <para>     <literal>local_normdevjitter</literal>Local calculated jitter (normal deviation)</para>
+                                               <para>     <literal>local_stdevjitter</literal> Local calculated jitter (standard deviation)</para>
+                                               <para>     <literal>local_count</literal>       Number of received packets</para>
+                                               <para>     <literal>remote_ssrc</literal>       Remote SSRC (stream ID)</para>
+                                               <para>     <literal>remote_lostpackets</literal>Remote lost packets</para>
+                                               <para>     <literal>remote_jitter</literal>     Remote reported jitter</para>
+                                               <para>     <literal>remote_maxjitter</literal>  Remote calculated jitter (maximum)</para>
+                                               <para>     <literal>remote_minjitter</literal>  Remote calculated jitter (minimum)</para>
+                                               <para>     <literal>remote_normdevjitter</literal>Remote calculated jitter (normal deviation)</para>
+                                               <para>     <literal>remote_stdevjitter</literal>Remote calculated jitter (standard deviation)</para>
+                                               <para>     <literal>remote_count</literal>      Number of transmitted packets</para>
+                                               <para>     <literal>remote_ssrc</literal>       Remote SSRC (stream ID)</para>
+                                               <para>     <literal>remote_lostpackets</literal>Remote lost packets</para>
+                                               <para>     <literal>remote_jitter</literal>     Remote reported jitter</para>
+                                               <para>     <literal>remote_maxjitter</literal>  Remote calculated jitter (maximum)</para>
+                                               <para>     <literal>remote_minjitter</literal>  Remote calculated jitter (minimum)</para>
+                                               <para>     <literal>remote_normdevjitter</literal>Remote calculated jitter (normal deviation)</para>
+                                               <para>     <literal>remote_stdevjitter</literal>Remote calculated jitter (standard deviation)</para>
+                                               <para>     <literal>remote_count</literal>      Number of transmitted packets</para>
+                                               <para>     <literal>rtt</literal>               Round trip time</para>
+                                               <para>     <literal>maxrtt</literal>            Round trip time (maximum)</para>
+                                               <para>     <literal>minrtt</literal>            Round trip time (minimum)</para>
+                                               <para>     <literal>normdevrtt</literal>        Round trip time (normal deviation)</para>
+                                               <para>     <literal>stdevrtt</literal>          Round trip time (standard deviation)</para>
+                                               <para>     <literal>all</literal>               All statistics (in a form suited to logging,
+                                               but not for parsing)</para>
+                                       </enum>
+                                       <enum name="rtpdest">
+                                               <para>R/O Get remote RTP destination information.</para>
+                                               <para>   This option takes one additional argument:</para>
+                                               <para>    Argument 1:</para>
+                                               <para>     <literal>audio</literal>             Get audio destination</para>
+                                               <para>     <literal>video</literal>             Get video destination</para>
+                                       </enum>
+                               </enumlist>
+                               <para><emphasis>chan_iax2</emphasis> provides the following additional options:</para>
+                               <enumlist>
+                                       <enum name="osptoken">
+                                               <para>R/W Get or set the OSP token information for a call.</para>
+                                       </enum>
+                                       <enum name="peerip">
+                                               <para>R/O Get the peer's ip address.</para>
+                                       </enum>
+                                       <enum name="peername">
+                                               <para>R/O Get the peer's username.</para>
+                                       </enum>
+                               </enumlist>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Gets/sets various pieces of information about the channel, additional <replaceable>item</replaceable> may
+                       be available from the channel driver; see its documentation for details. Any <replaceable>item</replaceable>
+                       requested that is not available on the current channel will return an empty string.</para>
+               </description>
+       </function>
+ ***/
+
 #define locked_copy_string(chan, dest, source, len) \
        do { \
                ast_channel_lock(chan); \
@@ -168,80 +330,6 @@ static int func_channel_write(struct ast_channel *chan, const char *function,
 
 static struct ast_custom_function channel_function = {
        .name = "CHANNEL",
-       .synopsis = "Gets/sets various pieces of information about the channel.",
-       .syntax = "CHANNEL(item)",
-       .desc = "Gets/set various pieces of information about the channel.\n"
-               "Standard items (provided by all channel technologies) are:\n"
-               "R/O    audioreadformat    format currently being read\n"
-               "R/O    audionativeformat  format used natively for audio\n"
-               "R/O    audiowriteformat   format currently being written\n"
-               "R/W    callgroup          call groups for call pickup\n"
-               "R/O    channeltype        technology used for channel\n"
-               "R/W    language           language for sounds played\n"
-               "R/W    musicclass         class (from musiconhold.conf) for hold music\n"
-               "R/W    parkinglot         parkinglot for parking\n"
-               "R/W    rxgain             set rxgain level on channel drivers that support it\n"
-               "R/O    state              state for channel\n"
-               "R/W    tonezone           zone for indications played\n"
-               "R/W    txgain             set txgain level on channel drivers that support it\n"
-               "R/O    videonativeformat  format used natively for video\n"
-#ifdef CHANNEL_TRACE
-               "R/W    trace              whether or not context tracing is enabled\n"
-#endif
-               "\n"
-               "chan_sip provides the following additional options:\n"
-               "R/O    peerip             Get the IP address of the peer\n"
-               "R/O    recvip             Get the source IP address of the peer\n"
-               "R/O    from               Get the URI from the From: header\n"
-               "R/O    uri                Get the URI from the Contact: header\n"
-               "R/O    useragent          Get the useragent\n"
-               "R/O    peername           Get the name of the peer\n"
-               "R/O    t38passthrough     1 if T38 is offered or enabled in this channel, otherwise 0\n"
-               "R/O    rtpqos             Get QOS information about the RTP stream\n"
-               "       This option takes two additional arguments:\n"
-               "  Argument 1:\n"
-               "    audio                 Get data about the audio stream\n"
-               "    video                 Get data about the video stream\n"
-               "    text                  Get data about the text stream\n"
-               "  Argument 2:\n"
-               "    local_ssrc            Local SSRC (stream ID)\n"
-               "    local_lostpackets     Local lost packets\n"
-               "    local_jitter          Local calculated jitter\n"
-               "    local_maxjitter       Local calculated jitter (maximum)\n"
-               "    local_minjitter       Local calculated jitter (minimum)\n"
-               "    local_normdevjitter   Local calculated jitter (normal deviation)\n"
-               "    local_stdevjitter     Local calculated jitter (standard deviation)\n"
-               "    local_count           Number of received packets\n"
-               "    remote_ssrc           Remote SSRC (stream ID)\n"
-               "    remote_lostpackets    Remote lost packets\n"
-               "    remote_jitter         Remote reported jitter\n"
-               "    remote_maxjitter      Remote calculated jitter (maximum)\n"
-               "    remote_minjitter      Remote calculated jitter (minimum)\n"
-               "    remote_normdevjitter  Remote calculated jitter (normal deviation)\n"
-               "    remote_stdevjitter    Remote calculated jitter (standard deviation)\n"
-               "    remote_count          Number of transmitted packets\n"
-               "    rtt                   Round trip time\n"
-               "    maxrtt                Round trip time (maximum)\n"
-               "    minrtt                Round trip time (minimum)\n"
-               "    normdevrtt            Round trip time (normal deviation)\n"
-               "    stdevrtt              Round trip time (standard deviation)\n"
-               "    all                   All statistics (in a form suited to logging, but not for parsing)\n"
-               "R/O    rtpdest            Get remote RTP destination information\n"
-               "       This option takes one additional argument:\n"
-               "  Argument 1:\n"
-               "    audio                 Get audio destination\n"
-               "    video                 Get video destination\n"
-               "\n"
-               "chan_iax2 provides the following additional options:\n"
-               "R/W    osptoken           Get or set the OSP token information for a call\n"
-               "R/O    peerip             Get the peer's ip address\n"
-               "R/O    peername           Get the peer's username\n"
-               "\n"
-               "Additional items may be available from the channel driver providing\n"
-               "the channel; see its documentation for details.\n"
-               "\n"
-               "Any item requested that is not available on the current channel will\n"
-               "return an empty string.\n",
        .read = func_channel_read,
        .write = func_channel_write,
 };
@@ -288,13 +376,6 @@ static int func_channels_read(struct ast_channel *chan, const char *function, ch
 
 static struct ast_custom_function channels_function = {
        .name = "CHANNELS",
-       .synopsis = "Gets the list of channels, optionally filtering by a regular expression.",
-       .syntax = "CHANNEL([regular expression])",
-       .desc =
-"Gets the list of channels, optionally filtering by a regular expression.  If\n"
-"no argument is provided, all known channels are returned.  The regular\n"
-"expression must correspond to the POSIX.2 specification, as shown in\n"
-"regex(7).  The list returned will be space-delimited.\n",
        .read = func_channels_read,
 };
 
index 5669f36559bfbde1222e1a1dd9b469af2269d978..21d291c2e5bcf7a10374befdc7bac6ee7faa078d 100644 (file)
@@ -36,6 +36,23 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/pbx.h"
 #include "asterisk/app.h"
 
+/*** DOCUMENTATION
+       <function name="AST_CONFIG" language="en_US">
+               <synopsis>
+                       Retrieve a variable from a configuration file.
+               </synopsis>
+               <syntax>
+                       <parameter name="config_file" required="true" />
+                       <parameter name="category" required="true" />
+                       <parameter name="variable_name" required="true" />
+               </syntax>
+               <description>
+                       <para>This function reads a variable from an Asterisk configuration file.</para>
+               </description>
+       </function>
+
+***/
+
 struct config_item {
        AST_RWLIST_ENTRY(config_item) entry;
        struct ast_config *cfg;
@@ -160,11 +177,6 @@ static int config_function_read(struct ast_channel *chan, const char *cmd, char
 
 static struct ast_custom_function config_function = {
        .name = "AST_CONFIG",
-       .syntax = "AST_CONFIG(config_file,category,variable_name)",
-       .synopsis = "Retrieve a variable from a configuration file",
-       .desc = 
-       "   This function reads a variable from an Asterisk configuration file.\n"
-       "",
        .read = config_function_read,
 };
 
index 96779b661c09dbc03ee0f51e3fe030f17776bd33..dda907ca2635583599bf70b4a7b06c0cffafc705 100644 (file)
@@ -34,6 +34,49 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/module.h"
 #include "asterisk/app.h"
 
+/*** DOCUMENTATION
+       <function name="SORT" language="en_US">
+               <synopsis>
+                       Sorts a list of key/vals into a list of keys, based upon the vals.      
+               </synopsis>
+               <syntax>
+                       <parameter name="keyval" required="true" argsep=":">
+                               <argument name="key1" required="true" />
+                               <argument name="val1" required="true" />
+                       </parameter>
+                       <parameter name="keyvaln" multiple="true" argsep=":">
+                               <argument name="key2" required="true" />
+                               <argument name="val2" required="true" />
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Takes a comma-separated list of keys and values, each separated by a colon, and returns a
+                       comma-separated list of the keys, sorted by their values.  Values will be evaluated as
+                       floating-point numbers.</para>
+               </description>
+       </function>
+       <function name="CUT" language="en_US">
+               <synopsis>
+                       Slices and dices strings, based upon a named delimiter.         
+               </synopsis>
+               <syntax>
+                       <parameter name="varname" required="true">
+                               <para>Variable you want cut</para>
+                       </parameter>
+                       <parameter name="char-delim" required="true">
+                               <para>Delimiter, defaults to <literal>-</literal></para>
+                       </parameter>
+                       <parameter name="range-spec" required="true">
+                               <para>Number of the field you want (1-based offset), may also be specified as a range (with <literal>-</literal>)
+                               or group of ranges and fields (with <literal>&amp;</literal>)</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Cut out information from a string (<replaceable>varname</replaceable>), based upon a named delimiter.</para>
+               </description>  
+       </function>
+ ***/
+
 /* Maximum length of any variable */
 #define MAXRESULT      1024
 
@@ -255,25 +298,11 @@ static int acf_cut_exec(struct ast_channel *chan, const char *cmd, char *data, c
 
 struct ast_custom_function acf_sort = {
        .name = "SORT",
-       .synopsis = "Sorts a list of key/vals into a list of keys, based upon the vals",
-       .syntax = "SORT(key1:val1[...][,keyN:valN])",
-       .desc =
-"Takes a comma-separated list of keys and values, each separated by a colon, and returns a\n"
-"comma-separated list of the keys, sorted by their values.  Values will be evaluated as\n"
-"floating-point numbers.\n",
        .read = acf_sort_exec,
 };
 
 struct ast_custom_function acf_cut = {
        .name = "CUT",
-       .synopsis = "Slices and dices strings, based upon a named delimiter.",
-       .syntax = "CUT(<varname>,<char-delim>,<range-spec>)",
-       .desc =
-"  varname    - variable you want cut\n"
-"  char-delim - defaults to '-'\n"
-"  range-spec - number of the field you want (1-based offset)\n"
-"             may also be specified as a range (with -)\n"
-"             or group of ranges and fields (with &)\n",
        .read = acf_cut_exec,
 };
 
index 374d4b859d2aaacf37443515bfe27e2984ccc58b..9c8e0bdf9068eee9eca369e3aefe87bbf240e90b 100644 (file)
@@ -40,6 +40,54 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/app.h"
 #include "asterisk/astdb.h"
 
+/*** DOCUMENTATION
+       <function name="DB" language="en_US">
+               <synopsis>
+                       Read from or write to the Asterisk database.
+               </synopsis>
+               <syntax argsep="/">
+                       <parameter name="family" required="true" />
+                       <parameter name="key" required="true" />
+               </syntax>
+               <description>
+                       <para>This function will read from or write a value to the Asterisk database.  On a
+                       read, this function returns the corresponding value from the database, or blank
+                       if it does not exist.  Reading a database value will also set the variable
+                       DB_RESULT.  If you wish to find out if an entry exists, use the DB_EXISTS
+                       function.</para>
+               </description>
+       </function>
+       <function name="DB_EXISTS" language="en_US">
+               <synopsis>
+                       Check to see if a key exists in the Asterisk database.
+               </synopsis>
+               <syntax argsep="/">
+                       <parameter name="family" required="true" />
+                       <parameter name="key" required="true" />
+               </syntax>
+               <description>
+                       <para>This function will check to see if a key exists in the Asterisk
+                       database. If it exists, the function will return <literal>1</literal>. If not,
+                       it will return <literal>0</literal>.  Checking for existence of a database key will
+                       also set the variable DB_RESULT to the key's value if it exists.</para>
+               </description>
+       </function>
+       <function name="DB_DELETE" language="en_US">
+               <synopsis>
+                       Return a value from the database and delete it.
+               </synopsis>
+               <syntax argsep="/">
+                       <parameter name="family" required="true" />
+                       <parameter name="key" required="true" />
+               </syntax>
+               <description>
+                       <para>This function will retrieve a value from the Asterisk database
+                       and then remove that key from the database. <variable>DB_RESULT</variable>
+                       will be set to the key's value if it exists.</para>
+               </description>
+       </function>
+ ***/
+
 static int function_db_read(struct ast_channel *chan, const char *cmd,
                            char *parse, char *buf, size_t len)
 {
@@ -100,14 +148,6 @@ static int function_db_write(struct ast_channel *chan, const char *cmd, char *pa
 
 static struct ast_custom_function db_function = {
        .name = "DB",
-       .synopsis = "Read from or write to the Asterisk database",
-       .syntax = "DB(<family>/<key>)",
-       .desc =
-"This function will read from or write a value to the Asterisk database.  On a\n"
-"read, this function returns the corresponding value from the database, or blank\n"
-"if it does not exist.  Reading a database value will also set the variable\n"
-"DB_RESULT.  If you wish to find out if an entry exists, use the DB_EXISTS\n"
-"function.\n",
        .read = function_db_read,
        .write = function_db_write,
 };
@@ -146,13 +186,6 @@ static int function_db_exists(struct ast_channel *chan, const char *cmd,
 
 static struct ast_custom_function db_exists_function = {
        .name = "DB_EXISTS",
-       .synopsis = "Check to see if a key exists in the Asterisk database",
-       .syntax = "DB_EXISTS(<family>/<key>)",
-       .desc =
-               "This function will check to see if a key exists in the Asterisk\n"
-               "database. If it exists, the function will return \"1\". If not,\n"
-               "it will return \"0\".  Checking for existence of a database key will\n"
-               "also set the variable DB_RESULT to the key's value if it exists.\n",
        .read = function_db_exists,
 };
 
@@ -194,12 +227,6 @@ static int function_db_delete(struct ast_channel *chan, const char *cmd,
 
 static struct ast_custom_function db_delete_function = {
        .name = "DB_DELETE",
-       .synopsis = "Return a value from the database and delete it",
-       .syntax = "DB_DELETE(<family>/<key>)",
-       .desc =
-               "This function will retrieve a value from the Asterisk database\n"
-               " and then remove that key from the database.  DB_RESULT\n"
-               "will be set to the key's value if it exists.\n",
        .read = function_db_delete,
 };
 
index 1cedb3e53f1b0b681bd41274aad0c6b28e303d00..f164cb7c14c2cadcf4c9cee22e31bcbf6d718ea2 100644 (file)
@@ -44,6 +44,57 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/astdb.h"
 #include "asterisk/app.h"
 
+/*** DOCUMENTATION
+       <function name="DEVICE_STATE" language="en_US">
+               <synopsis>
+                       Get or Set a device state.
+               </synopsis>
+               <syntax>
+                       <parameter name="device" required="true" />
+               </syntax>
+               <description>
+                       <para>The DEVICE_STATE function can be used to retrieve the device state from any
+                       device state provider. For example:</para>
+                       <para>NoOp(SIP/mypeer has state ${DEVICE_STATE(SIP/mypeer)})</para>
+                       <para>NoOp(Conference number 1234 has state ${DEVICE_STATE(MeetMe:1234)})</para>
+                       <para>The DEVICE_STATE function can also be used to set custom device state from
+                       the dialplan.  The <literal>Custom:</literal> prefix must be used. For example:</para>
+                       <para>Set(DEVICE_STATE(Custom:lamp1)=BUSY)</para>
+                       <para>Set(DEVICE_STATE(Custom:lamp2)=NOT_INUSE)</para>
+                       <para>You can subscribe to the status of a custom device state using a hint in
+                       the dialplan:</para>
+                       <para>exten => 1234,hint,Custom:lamp1</para>
+                       <para>The possible values for both uses of this function are:</para>
+                       <para>UNKNOWN | NOT_INUSE | INUSE | BUSY | INVALID | UNAVAILABLE | RINGING |
+                       RINGINUSE | ONHOLD</para>
+               </description>
+       </function>
+       <function name="HINT" language="en_US">
+               <synopsis>
+                       Get the devices set for a dialplan hint.
+               </synopsis>
+               <syntax>
+                       <parameter name="extension" required="true" argsep="@">
+                               <argument name="extension" required="true" />
+                               <argument name="context" />
+                       </parameter>
+                       <parameter name="options">
+                               <optionlist>
+                                       <option name="n">
+                                               <para>Retrieve name on the hint instead of list of devices.</para>
+                                       </option>
+                               </optionlist>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>The HINT function can be used to retrieve the list of devices that are
+                       mapped to a dialplan hint. For example:</para>
+                       <para>NoOp(Hint for Extension 1234 is ${HINT(1234)})</para>
+               </description>
+       </function>
+ ***/
+
+
 static const char astdb_family[] = "CustomDevstate";
 
 static int devstate_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
@@ -296,40 +347,12 @@ static struct ast_cli_entry cli_funcdevstate[] = {
 
 static struct ast_custom_function devstate_function = {
        .name = "DEVICE_STATE",
-       .synopsis = "Get or Set a device state",
-       .syntax = "DEVICE_STATE(device)",
-       .desc =
-       "  The DEVICE_STATE function can be used to retrieve the device state from any\n"
-       "device state provider.  For example:\n"
-       "   NoOp(SIP/mypeer has state ${DEVICE_STATE(SIP/mypeer)})\n"
-       "   NoOp(Conference number 1234 has state ${DEVICE_STATE(MeetMe:1234)})\n"
-       "\n"
-       "  The DEVICE_STATE function can also be used to set custom device state from\n"
-       "the dialplan.  The \"Custom:\" prefix must be used.  For example:\n"
-       "  Set(DEVICE_STATE(Custom:lamp1)=BUSY)\n"
-       "  Set(DEVICE_STATE(Custom:lamp2)=NOT_INUSE)\n"
-       "You can subscribe to the status of a custom device state using a hint in\n"
-       "the dialplan:\n"
-       "  exten => 1234,hint,Custom:lamp1\n"
-       "\n"
-       "  The possible values for both uses of this function are:\n"
-       "UNKNOWN | NOT_INUSE | INUSE | BUSY | INVALID | UNAVAILABLE | RINGING\n"
-       "RINGINUSE | ONHOLD\n",
        .read = devstate_read,
        .write = devstate_write,
 };
 
 static struct ast_custom_function hint_function = {
        .name = "HINT",
-       .synopsis = "Get the devices set for a dialplan hint",
-       .syntax = "HINT(extension[@context][|options])",
-       .desc =
-       "  The HINT function can be used to retrieve the list of devices that are\n"
-       "mapped to a dialplan hint.  For example:\n"
-       "   NoOp(Hint for Extension 1234 is ${HINT(1234)})\n"
-       "Options:\n"
-       "   'n' - Retrieve name on the hint instead of list of devices\n"
-       "",
        .read = hint_read,
 };
 
index c3674beb93315f64b2afef867537f22d2c2410e9..4e4f6338922cedd921287db7653e785eb4351b60 100644 (file)
@@ -39,6 +39,40 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/astobj2.h"
 #include "asterisk/astdb.h"
 
+/*** DOCUMENTATION
+       <function name="DIALGROUP" language="en_US">
+               <synopsis>
+                       Manages a group of users for dialing.
+               </synopsis>
+               <syntax>
+                       <parameter name="group" required="true" />
+                       <parameter name="op">
+                               <para>The operation name, possible values are:</para>
+                               <para><literal>add</literal> - add a channel name or interface (write-only)</para>
+                               <para><literal>del</literal> - remove a channel name or interface (write-only)</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Presents an interface meant to be used in concert with the Dial
+                       application, by presenting a list of channels which should be dialled when
+                       referenced.</para>
+                       <para>When DIALGROUP is read from, the argument is interpreted as the particular
+                       <replaceable>group</replaceable> for which a dial should be attempted.  When DIALGROUP is written to
+                       with no arguments, the entire list is replaced with the argument specified.</para>
+                       <para>Functionality is similar to a queue, except that when no interfaces are
+                       available, execution may continue in the dialplan.  This is useful when
+                       you want certain people to be the first to answer any calls, with immediate
+                       fallback to a queue when the front line people are busy or unavailable, but
+                       you still want front line people to log in and out of that group, just like
+                       a queue.</para>
+                       <para>Example:</para>
+                       <para>exten => 1,1,Set(DIALGROUP(mygroup,add)=SIP/10)</para>
+                       <para>exten => 1,n,Set(DIALGROUP(mygroup,add)=SIP/20)</para>
+                       <para>exten => 1,n,Dial(${DIALGROUP(mygroup)})</para>
+               </description>
+       </function>
+ ***/
+
 static struct ao2_container *group_container = NULL;
 
 struct group_entry {
@@ -232,24 +266,6 @@ static int dialgroup_write(struct ast_channel *chan, const char *cmd, char *data
 
 static struct ast_custom_function dialgroup_function = {
        .name = "DIALGROUP",
-       .synopsis = "Manages a group of users for dialing",
-       .syntax = "DIALGROUP(<group>[,op])",
-       .desc =
-"  DIALGROUP presents an interface meant to be used in concert with the Dial\n"
-"application, by presenting a list of channels which should be dialled when\n"
-"referenced.\n"
-"  When DIALGROUP is read from, the argument is interpreted as the particular\n"
-"group for which a dial should be attempted.  When DIALGROUP is written to\n"
-"with no arguments, the entire list is replaced with the argument specified.\n"
-"Other operations are as follows:\n"
-"  add - add a channel name or interface (write-only)\n"
-"  del - remove a channel name or interface (write-only)\n\n"
-"Functionality is similar to a queue, except that when no interfaces are\n"
-"available, execution may continue in the dialplan.  This is useful when\n"
-"you want certain people to be the first to answer any calls, with immediate\n"
-"fallback to a queue when the front line people are busy or unavailable, but\n"
-"you still want front line people to log in and out of that group, just like\n"
-"a queue.\n",
        .read = dialgroup_read,
        .write = dialgroup_write,
 };
index 6d4c488f6068c9fd9458cde2a04665e0ba504924..0e371d2c8dc8f5327b5ea527bad3dc8ddf4200af 100644 (file)
@@ -33,6 +33,23 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/pbx.h"
 #include "asterisk/app.h"
 
+/*** DOCUMENTATION
+       <function name="DIALPLAN_EXISTS" language="en_US">
+               <synopsis>
+                       Checks the existence of a dialplan target.
+               </synopsis>
+               <syntax>
+                       <parameter name="context" required="true" />
+                       <parameter name="extension" />
+                       <parameter name="priority" />
+               </syntax>
+               <description>
+                       <para>This function returns <literal>1</literal> if the target exits. Otherwise, it returns <literal>0</literal>.</para>
+               </description>
+       </function>
+
+ ***/
+
 static int isexten_function_read(struct ast_channel *chan, const char *cmd, char *data, 
        char *buf, size_t len) 
 {
@@ -87,9 +104,6 @@ static int isexten_function_read(struct ast_channel *chan, const char *cmd, char
 
 static struct ast_custom_function isexten_function = {
        .name = "DIALPLAN_EXISTS",
-       .syntax = "DIALPLAN_EXISTS(context[,extension[,priority]])",
-       .synopsis = "Checks the existence of a dialplan target.",
-       .desc = "This function returns 1 if the target exits.  Otherwise, it returns 0.\n",
        .read = isexten_function_read,
 };
 
index 54893a9bfedd7b888973d6be4e97a8eecdd3bcfd..525c935f6ae2229bc313c9e3c3296f25eb1eda91 100644 (file)
@@ -46,6 +46,109 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/enum.h"
 #include "asterisk/app.h"
 
+/*** DOCUMENTATION
+       <function name="ENUMQUERY" language="en_US">
+               <synopsis>
+                       Initiate an ENUM query.
+               </synopsis>
+               <syntax>
+                       <parameter name="number" required="true" />
+                       <parameter name="method-type">
+                               <para>If no <replaceable>method-type</replaceable> is given, the default will be
+                               <literal>sip</literal>.</para>
+                       </parameter>
+                       <parameter name="zone-suffix">
+                               <para>If no <replaceable>zone-suffix</replaceable> is given, the default will be
+                               <literal>e164.arpa</literal></para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>This will do a ENUM lookup of the given phone number.</para>
+               </description>
+       </function>
+       <function name="ENUMRESULT" language="en_US">
+               <synopsis>
+                       Retrieve results from a ENUMQUERY.
+               </synopsis>
+               <syntax>
+                       <parameter name="id" required="true">
+                               <para>The identifier returned by the ENUMQUERY function.</para>
+                       </parameter>
+                       <parameter name="resultnum" required="true">
+                               <para>The number of the result that you want to retrieve.</para>
+                               <para>Results start at <literal>1</literal>. If this argument is specified
+                               as <literal>getnum</literal>, then it will return the total number of results 
+                               that are available.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>This function will retrieve results from a previous use
+                       of the ENUMQUERY function.</para>
+               </description>
+       </function>     
+       <function name="ENUMLOOKUP" language="en_US">
+               <synopsis>
+                       General or specific querying of NAPTR records for ENUM or ENUM-like DNS pointers.
+               </synopsis>
+               <syntax>
+                       <parameter name="number" required="true" />
+                       <parameter name="method-type">
+                               <para>If no <replaceable>method-type</replaceable> is given, the default will be
+                                <literal>sip</literal>.</para>
+                       </parameter>
+                       <parameter name="options">
+                               <optionlist>
+                                       <option name="c">
+                                               <para>Returns an integer count of the number of NAPTRs of a certain RR type.</para>
+                                               <para>Combination of <literal>c</literal> and Method-type of <literal>ALL</literal> will
+                                               return a count of all NAPTRs for the record.</para>
+                                       </option>
+                                       <option name="u">
+                                               <para>Returns the full URI and does not strip off the URI-scheme.</para>
+                                       </option>
+                                       <option name="s">
+                                               <para>Triggers ISN specific rewriting.</para>
+                                       </option>
+                                       <option name="i">
+                                               <para>Looks for branches into an Infrastructure ENUM tree.</para>
+                                       </option>
+                                       <option name="d">
+                                               <para>for a direct DNS lookup without any flipping of digits.</para>
+                                       </option>
+                               </optionlist>   
+                       </parameter>
+                       <parameter name="record#">
+                               <para>If no <replaceable>record#</replaceable> is given, 
+                               defaults to <literal>1</literal>.</para>
+                       </parameter>
+                       <parameter name="zone-suffix">
+                               <para>If no <replaceable>zone-suffix</replaceable> is given, the default will be
+                               <literal>e164.arpa</literal></para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>For more information see <filename>doc/asterisk.pdf</filename>.</para>
+               </description>
+       </function>
+       <function name="TXTCIDNAME" language="en_US">
+               <synopsis>
+                       TXTCIDNAME looks up a caller name via DNS.
+               </synopsis>
+               <syntax>
+                       <parameter name="number" required="true" />
+                       <parameter name="zone-suffix">
+                               <para>If no <replaceable>zone-suffix</replaceable> is given, the default will be
+                               <literal>e164.arpa</literal></para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>This function looks up the given phone number in DNS to retrieve
+                       the caller id name.  The result will either be blank or be the value
+                       found in the TXT record in DNS.</para>
+               </description>
+       </function>
+ ***/
+
 static char *synopsis = "Syntax: ENUMLOOKUP(number[,Method-type[,options[,record#[,zone-suffix]]]])\n";
 
 static int function_enum(struct ast_channel *chan, const char *cmd, char *data,
@@ -295,44 +398,16 @@ finish:
 
 static struct ast_custom_function enum_query_function = {
        .name = "ENUMQUERY",
-       .synopsis = "Initiate an ENUM query",
-       .syntax = "ENUMQUERY(number[,Method-type[,zone-suffix]])",
-       .desc = "This will do a ENUM lookup of the given phone number.\n"
-       "If no method-tpye is given, the default will be sip. If no\n"
-       "zone-suffix is given, the default will be \"e164.arpa\".\n"
-       "The result of this function will be a numeric ID that can\n"
-       "be used to retrieve the results using the ENUMRESULT function.\n",
        .read = enum_query_read,
 };
 
 static struct ast_custom_function enum_result_function = {
        .name = "ENUMRESULT",
-       .synopsis = "Retrieve results from a ENUMQUERY",
-       .syntax = "ENUMRESULT(id,resultnum)",
-       .desc = "This function will retrieve results from a previous use\n"
-       "of the ENUMQUERY function.\n"
-       "  id - This argument is the identifier returned by the ENUMQUERY function.\n"
-       "  resultnum - This is the number of the result that you want to retrieve.\n"
-       "       Results start at 1.  If this argument is specified as \"getnum\",\n"
-       "       then it will return the total number of results that are available.\n",
        .read = enum_result_read,
 };
 
 static struct ast_custom_function enum_function = {
        .name = "ENUMLOOKUP",
-       .synopsis =
-               "General or specific querying of NAPTR records for ENUM or ENUM-like DNS pointers",
-       .syntax =
-               "ENUMLOOKUP(number[,Method-type[,options[,record#[,zone-suffix]]]])",
-       .desc =
-               "Option 'c' returns an integer count of the number of NAPTRs of a certain RR type.\n"
-               "Combination of 'c' and Method-type of 'ALL' will return a count of all NAPTRs for the record.\n"
-               "Option 'u' returns the full URI and does not strip off the URI-scheme.\n"
-               "Option 's' triggers ISN specific rewriting\n"
-               "Option 'i' looks for branches into an Infrastructure ENUM tree\n"
-               "Option 'd' for a direct DNS lookup without any flipping of digits\n"
-               "Defaults are: Method-type=sip, no options, record=1, zone-suffix=e164.arpa\n\n"
-               "For more information, see doc/asterisk.pdf",
        .read = function_enum,
 };
 
@@ -370,12 +445,6 @@ static int function_txtcidname(struct ast_channel *chan, const char *cmd,
 
 static struct ast_custom_function txtcidname_function = {
        .name = "TXTCIDNAME",
-       .synopsis = "TXTCIDNAME looks up a caller name via DNS",
-       .syntax = "TXTCIDNAME(<number>[,zone-suffix])",
-       .desc =
-               "This function looks up the given phone number in DNS to retrieve\n"
-               "the caller id name.  The result will either be blank or be the value\n"
-               "found in the TXT record in DNS. The default zone-suffix is e164.arpa.\n",
        .read = function_txtcidname,
 };
 
index 4eba211bb0d6f23ba28cf635d3b4682b92692977..401dc28e379558d0fedf83b0f618b4df3ea38a01 100644 (file)
@@ -33,6 +33,59 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/utils.h"
 #include "asterisk/app.h"
 
+/*** DOCUMENTATION
+       <function name="ENV" language="en_US">
+               <synopsis>
+                       Gets or sets the environment variable specified.
+               </synopsis>
+               <syntax>
+                       <parameter name="varname" required="true">
+                               <para>Enviroment variable name</para>
+                       </parameter>
+               </syntax>
+               <description>
+               </description>
+       </function>
+       <function name="STAT" language="en_US">
+               <synopsis>
+                       Does a check on the specified file.
+               </synopsis>
+               <syntax>
+                       <parameter name="flag" required="true">
+                               <para>Flag may be one of the following:</para>
+                               <para>d - Checks if the file is a directory.</para>
+                               <para>e - Checks if the file exists.</para>
+                               <para>f - Checks if the file is a regular file.</para>
+                               <para>m - Returns the file mode (in octal)</para>
+                               <para>s - Returns the size (in bytes) of the file</para>
+                               <para>A - Returns the epoch at which the file was last accessed.</para>
+                               <para>C - Returns the epoch at which the inode was last changed.</para>
+                               <para>M - Returns the epoch at which the file was last modified.</para>
+                       </parameter>
+                       <parameter name="filename" required="true" />
+               </syntax>
+               <description>
+               </description>
+       </function>
+       <function name="FILE" language="en_US">
+               <synopsis>
+                       Obtains the contents of a file.
+               </synopsis>
+               <syntax>
+                       <parameter name="filename" required="true" />
+                       <parameter name="offset" required="true">
+                               <para>Maybe specified as any number. if negative <replaceable>offset</replaceable> specifies the number
+                               of bytes back from the end of the file.</para>
+                       </parameter>
+                       <parameter name="length" required="true">
+                               <para>If specified, will limit the length of the data read to that size.</para>
+                       </parameter>
+               </syntax>
+               <description>
+               </description>
+       </function>
+ ***/
+
 static int env_read(struct ast_channel *chan, const char *cmd, char *data,
                    char *buf, size_t len)
 {
@@ -151,43 +204,23 @@ static int file_read(struct ast_channel *chan, const char *cmd, char *data, char
 
 static struct ast_custom_function env_function = {
        .name = "ENV",
-       .synopsis = "Gets or sets the environment variable specified",
-       .syntax = "ENV(<envname>)",
        .read = env_read,
-       .write = env_write,
+       .write = env_write
 };
 
 static struct ast_custom_function stat_function = {
        .name = "STAT",
-       .synopsis = "Does a check on the specified file",
-       .syntax = "STAT(<flag>,<filename>)",
-       .read = stat_read,
-       .desc =
-               "flag may be one of the following:\n"
-               "  d - Checks if the file is a directory\n"
-               "  e - Checks if the file exists\n"
-               "  f - Checks if the file is a regular file\n"
-               "  m - Returns the file mode (in octal)\n"
-               "  s - Returns the size (in bytes) of the file\n"
-               "  A - Returns the epoch at which the file was last accessed\n"
-               "  C - Returns the epoch at which the inode was last changed\n"
-               "  M - Returns the epoch at which the file was last modified\n",
+       .read = stat_read
 };
 
 static struct ast_custom_function file_function = {
        .name = "FILE",
-       .synopsis = "Obtains the contents of a file",
-       .syntax = "FILE(<filename>,<offset>,<length>)",
-       .read = file_read,
+       .read = file_read
        /*
         * Some enterprising programmer could probably add write functionality
         * to FILE(), although I'm not sure how useful it would be.  Hence why
         * it's called FILE and not READFILE (like the app was).
         */
-       .desc =
-"<offset> may be specified as any number.  If negative, <offset> specifies\n"
-"    the number of bytes back from the end of the file.\n"
-"<length>, if specified, will limit the length of the data read to that size.\n",
 };
 
 static int unload_module(void)
index 8866d89b9cf0c69c0297472c29847111c1e5974f..7f22885608e8d28e657f698a56ab7a831da979a9 100644 (file)
@@ -36,6 +36,29 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/utils.h"
 #include "asterisk/devicestate.h"
 
+/*** DOCUMENTATION
+       <function name="EXTENSION_STATE" language="en_US">
+               <synopsis>
+                       Get an extension's state.
+               </synopsis>     
+               <syntax argsep="@">
+                       <parameter name="extension" required="true" />
+                       <parameter name="context">
+                               <para>If it is not specified defaults to <literal>default</literal>.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>The EXTENSION_STATE function can be used to retrieve the state from any
+                       hinted extension. For example:</para>
+                       <para>NoOp(1234@default has state ${EXTENSION_STATE(1234)})</para>
+                       <para>NoOp(4567@home has state ${EXTENSION_STATE(4567@home)})</para>
+                       <para>The possible values returned by this function are:</para>
+                       <para>UNKNOWN | NOT_INUSE | INUSE | BUSY | INVALID | UNAVAILABLE | RINGING |
+                       RINGINUSE | HOLDINUSE | ONHOLD</para>
+               </description>
+       </function>
+ ***/
+
 static const char *ast_extstate_str(int state)
 {
        const char *res = "UNKNOWN";
@@ -98,17 +121,6 @@ static int extstate_read(struct ast_channel *chan, const char *cmd, char *data,
 
 static struct ast_custom_function extstate_function = {
        .name = "EXTENSION_STATE",
-       .synopsis = "Get an extension's state",
-       .syntax = "EXTENSION_STATE(extension[@context])",
-       .desc =
-       "  The EXTENSION_STATE function can be used to retrieve the state from any\n"
-       "hinted extension.  For example:\n"
-       "   NoOp(1234@default has state ${EXTENSION_STATE(1234)})\n"
-       "   NoOp(4567@home has state ${EXTENSION_STATE(4567@home)})\n"
-       "\n"
-       "  The possible values returned by this function are:\n"
-       "UNKNOWN | NOT_INUSE | INUSE | BUSY | INVALID | UNAVAILABLE | RINGING\n"
-       "RINGINUSE | HOLDINUSE | ONHOLD\n",
        .read = extstate_read,
 };
 
index 3380cef12a63feb47b485ebbf4f56119e5cccb1a..74df1757c67581b907df87628c3dcbb3918add6f 100644 (file)
@@ -37,6 +37,51 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/app.h"
 #include "asterisk/manager.h"
 
+/*** DOCUMENTATION
+       <function name="GLOBAL" language="en_US">
+               <synopsis>
+                       Gets or sets the global variable specified.
+               </synopsis>
+               <syntax>
+                       <parameter name="varname" required="true">
+                               <para>Global variable name</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Set or get the value of a global variable specified in <replaceable>varname</replaceable></para>
+               </description>
+       </function>
+       <function name="SHARED" language="en_US">
+               <synopsis>
+                       Gets or sets the shared variable specified.
+               </synopsis>
+               <syntax>
+                       <parameter name="varname" required="true">
+                               <para>Variable name</para>
+                       </parameter>
+                       <parameter name="channel">
+                               <para>If not specified will default to current channel. It is the complete
+                               channel name: <literal>SIP/12-abcd1234</literal> or the prefix only <literal>SIP/12</literal>.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Implements a shared variable area, in which you may share variables between
+                       channels.</para>
+                       <para>The variables used in this space are separate from the general namespace of
+                       the channel and thus <variable>SHARED(foo)</variable> and <variable>foo</variable> 
+                       represent two completely different variables, despite sharing the same name.</para>
+                       <para>Finally, realize that there is an inherent race between channels operating
+                       at the same time, fiddling with each others' internal variables, which is why
+                       this special variable namespace exists; it is to remind you that variables in
+                       the SHARED namespace may change at any time, without warning.  You should
+                       therefore take special care to ensure that when using the SHARED namespace,
+                       you retrieve the variable and store it in a regular channel variable before
+                       using it in a set of calculations (or you might be surprised by the result).</para>
+               </description>
+       </function>
+
+ ***/
+
 static void shared_variable_free(void *data);
 
 static struct ast_datastore_info shared_variable_info = {
@@ -76,8 +121,6 @@ static int global_write(struct ast_channel *chan, const char *cmd, char *data, c
 
 static struct ast_custom_function global_function = {
        .name = "GLOBAL",
-       .synopsis = "Gets or sets the global variable specified",
-       .syntax = "GLOBAL(<varname>)",
        .read = global_read,
        .write = global_write,
 };
@@ -203,25 +246,6 @@ static int shared_write(struct ast_channel *chan, const char *cmd, char *data, c
 
 static struct ast_custom_function shared_function = {
        .name = "SHARED",
-       .synopsis = "Gets or sets the shared variable specified",
-       .syntax = "SHARED(<varname>[,<channel>])",
-       .desc =
-"Implements a shared variable area, in which you may share variables between\n"
-"channels.  If channel is unspecified, defaults to the current channel.  Note\n"
-"that the channel name may be the complete name (i.e. SIP/12-abcd1234) or the\n"
-"prefix only (i.e. SIP/12).\n"
-"\n"
-"The variables used in this space are separate from the general namespace of\n"
-"the channel and thus ${SHARED(foo)} and ${foo} represent two completely\n"
-"different variables, despite sharing the same name.\n"
-"\n"
-"Finally, realize that there is an inherent race between channels operating\n"
-"at the same time, fiddling with each others' internal variables, which is why\n"
-"this special variable namespace exists; it is to remind you that variables in\n"
-"the SHARED namespace may change at any time, without warning.  You should\n"
-"therefore take special care to ensure that when using the SHARED namespace,\n"
-"you retrieve the variable and store it in a regular channel variable before\n"
-"using it in a set of calculations (or you might be surprised by the result).\n",
        .read = shared_read,
        .write = shared_write,
 };
index b70a42e94ae13a5f9e2ccf835915ee23cca5ecfa..181855015aa9badfdee49661342222fa992724d1 100644 (file)
@@ -31,6 +31,67 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/utils.h"
 #include "asterisk/app.h"
 
+/*** DOCUMENTATION
+       <function name="GROUP_COUNT" language="en_US">
+               <synopsis>
+                       Counts the number of channels in the specified group.
+               </synopsis>
+               <syntax argsep="@">
+                       <parameter name="groupname">
+                               <para>Group name.</para>
+                       </parameter>
+                       <parameter name="category">
+                               <para>Category name</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Calculates the group count for the specified group, or uses the
+                       channel's current group if not specifed (and non-empty).</para>
+               </description>
+       </function>
+       <function name="GROUP_MATCH_COUNT" language="en_US">
+               <synopsis>
+                       Counts the number of channels in the groups matching the specified pattern.
+               </synopsis>
+               <syntax argsep="@">
+                       <parameter name="groupmatch" required="true">
+                               <para>A standard regular expression used to match a group name.</para>
+                       </parameter>
+                       <parameter name="category">
+                               <para>Category name.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Calculates the group count for all groups that match the specified pattern.
+                       Uses standard regular expression matching (see regex(7)).</para>
+               </description>
+       </function>
+       <function name="GROUP" language="en_US">
+               <synopsis>
+                       Gets or sets the channel group.
+               </synopsis>
+               <syntax>
+                       <parameter name="category">
+                               <para>Category name.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para><replaceable>category</replaceable> can be employed for more fine grained group management. Each channel 
+                       can only be member of exactly one group per <replaceable>category</replaceable>.</para>
+               </description>
+       </function>
+       <function name="GROUP_LIST" language="en_US">
+               <synopsis>
+                       Gets a list of the groups set on a channel.
+               </synopsis>
+               <syntax />
+               <description>
+                       <para>Gets a list of the groups set on a channel.</para>
+               </description>
+       </function>
+
+ ***/
+
 static int group_count_function_read(struct ast_channel *chan, const char *cmd,
                                     char *data, char *buf, size_t len)
 {
@@ -72,11 +133,6 @@ static int group_count_function_read(struct ast_channel *chan, const char *cmd,
 
 static struct ast_custom_function group_count_function = {
        .name = "GROUP_COUNT",
-       .syntax = "GROUP_COUNT([groupname][@category])",
-       .synopsis = "Counts the number of channels in the specified group",
-       .desc =
-               "Calculates the group count for the specified group, or uses the\n"
-               "channel's current group if not specifed (and non-empty).\n",
        .read = group_count_function_read,
 };
 
@@ -102,12 +158,6 @@ static int group_match_count_function_read(struct ast_channel *chan,
 
 static struct ast_custom_function group_match_count_function = {
        .name = "GROUP_MATCH_COUNT",
-       .syntax = "GROUP_MATCH_COUNT(groupmatch[@category])",
-       .synopsis =
-               "Counts the number of channels in the groups matching the specified pattern",
-       .desc =
-               "Calculates the group count for all groups that match the specified pattern.\n"
-               "Uses standard regular expression matching (see regex(7)).\n",
        .read = group_match_count_function_read,
        .write = NULL,
 };
@@ -159,9 +209,6 @@ static int group_function_write(struct ast_channel *chan, const char *cmd,
 
 static struct ast_custom_function group_function = {
        .name = "GROUP",
-       .syntax = "GROUP([category])",
-       .synopsis = "Gets or sets the channel group.",
-       .desc = "Gets or sets the channel group.\n",
        .read = group_function_read,
        .write = group_function_write,
 };
@@ -204,9 +251,6 @@ static int group_list_function_read(struct ast_channel *chan, const char *cmd,
 
 static struct ast_custom_function group_list_function = {
        .name = "GROUP_LIST",
-       .syntax = "GROUP_LIST()",
-       .synopsis = "Gets a list of the groups set on a channel.",
-       .desc = "Gets a list of the groups set on a channel.\n",
        .read = group_list_function_read,
        .write = NULL,
 };
index 74f32412b2ec0c3c5f27776b2a292b42cebacf55..231b4880f24b4834843003982ebbbb1f60c353dd 100644 (file)
@@ -41,6 +41,32 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/utils.h"
 #include "asterisk/app.h"
 
+/*** DOCUMENTATION
+       <function name="ICONV" language="en_US">
+               <synopsis>
+                       Converts charsets of strings.   
+               </synopsis>
+               <syntax>
+                       <parameter name="in-charset" required="true">
+                               <para>Input charset</para>
+                       </parameter>
+                       <parameter name="out-charset" required="true">
+                               <para>Output charset</para>
+                       </parameter>
+                       <parameter name="string" required="true">
+                               <para>String to convert, from <replaceable>in-charset</replaceable> to <replaceable>out-charset</replaceable></para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Converts string from <replaceable>in-charset</replaceable> into <replaceable>out-charset</replaceable>.
+                       For available charsets, use <literal>iconv -l</literal> on your shell command line.</para>
+                       <note><para>Due to limitations within the API, ICONV will not currently work with
+                       charsets with embedded NULLs. If found, the string will terminate.</para></note>
+               </description>
+       </function>
+ ***/
+
+
 /*! 
  * Some systems define the second arg to iconv() as (const char *),
  * while others define it as (char *).  Cast it to a (void *) to 
@@ -101,14 +127,7 @@ static int iconv_read(struct ast_channel *chan, const char *cmd, char *arguments
 
 static struct ast_custom_function iconv_function = {
        .name = "ICONV",
-       .synopsis = "Converts charsets of strings.",
-       .desc =
-"Converts string from in-charset into out-charset.  For available charsets,\n"
-"use 'iconv -l' on your shell command line.\n"
-"Note: due to limitations within the API, ICONV will not currently work with\n"
-"charsets with embedded NULLs.  If found, the string will terminate.\n",
-       .syntax = "ICONV(in-charset,out-charset,string)",
-       .read = iconv_read,
+       .read = iconv_read
 };
 
 static int unload_module(void)
index 133ea3e22d315daaf10ba3f83d92cd2afb14493a..d6df6d0efaead7a4d1f93d162b708cd96dd6e2e0 100644 (file)
@@ -37,6 +37,53 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/module.h"
 #include "asterisk/linkedlists.h"
 
+/*** DOCUMENTATION
+       <function name="LOCK" language="en_US">
+               <synopsis>
+                       Attempt to obtain a named mutex.
+               </synopsis>
+               <syntax>
+                       <parameter name="lockname" required="true" />
+               </syntax>
+               <description>
+                       <para>Attempts to grab a named lock exclusively, and prevents other channels from
+                       obtaining the same lock.  LOCK will wait for the lock to become available.
+                       Returns <literal>1</literal> if the lock was obtained or <literal>0</literal> on error.</para>
+                       <note><para>To avoid the possibility of a deadlock, LOCK will only attempt to
+                       obtain the lock for 3 seconds if the channel already has another lock.</para></note>
+               </description>
+       </function>
+       <function name="TRYLOCK" language="en_US">
+               <synopsis>
+                       Attempt to obtain a named mutex.
+               </synopsis>
+               <syntax>
+                       <parameter name="lockname" required="true" />
+               </syntax>
+               <description>
+                       <para>Attempts to grab a named lock exclusively, and prevents other channels
+                       from obtaining the same lock.  Returns <literal>1</literal> if the lock was 
+                       available or <literal>0</literal> otherwise.</para>
+               </description>
+       </function>
+       <function name="UNLOCK" language="en_US">
+               <synopsis>
+                       Unlocks a named mutex.
+               </synopsis>
+               <syntax>
+                       <parameter name="lockname" required="true" />
+               </syntax>
+               <description>
+                       <para>Unlocks a previously locked mutex. Returns <literal>1</literal> if the channel 
+                       had a lock or <literal>0</literal> otherwise.</para>
+                       <note><para>It is generally unnecessary to unlock in a hangup routine, as any locks 
+                       held are automatically freed when the channel is destroyed.</para></note>
+               </description>
+       </function>
+ ***/
+
+
+
 AST_LIST_HEAD_STATIC(locklist, lock_frame);
 
 static void lock_free(void *data);
@@ -276,36 +323,16 @@ static int trylock_read(struct ast_channel *chan, const char *cmd, char *data, c
 
 static struct ast_custom_function lock_function = {
        .name = "LOCK",
-       .synopsis = "Attempt to obtain a named mutex",
-       .desc =
-"Attempts to grab a named lock exclusively, and prevents other channels from\n"
-"obtaining the same lock.  LOCK will wait for the lock to become available.\n"
-"Returns 1 if the lock was obtained or 0 on error.\n\n"
-"Note: to avoid the possibility of a deadlock, LOCK will only attempt to\n"
-"obtain the lock for 3 seconds if the channel already has another lock.\n",
-       .syntax = "LOCK(<lockname>)",
        .read = lock_read,
 };
 
 static struct ast_custom_function trylock_function = {
        .name = "TRYLOCK",
-       .synopsis = "Attempt to obtain a named mutex",
-       .desc =
-"Attempts to grab a named lock exclusively, and prevents other channels\n"
-"from obtaining the same lock.  Returns 1 if the lock was available or 0\n"
-"otherwise.\n",
-       .syntax = "TRYLOCK(<lockname>)",
        .read = trylock_read,
 };
 
 static struct ast_custom_function unlock_function = {
        .name = "UNLOCK",
-       .synopsis = "Unlocks a named mutex",
-       .desc =
-"Unlocks a previously locked mutex.  Note that it is generally unnecessary to\n"
-"unlock in a hangup routine, as any locks held are automatically freed when the\n"
-"channel is destroyed.  Returns 1 if the channel had a lock or 0 otherwise.\n",
-       .syntax = "UNLOCK(<lockname>)",
        .read = unlock_read,
 };
 
index 7fca070aa828ee462a884c36f1a6667f2462828c..ef644f43f68536c11d6e350c5ed6583019c9283e 100644 (file)
@@ -34,6 +34,83 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/utils.h"
 #include "asterisk/app.h"
 
+/*** DOCUMENTATION
+       <function name="ISNULL" language="en_US">
+               <synopsis>
+                       Check if a value is NULL.
+               </synopsis>
+               <syntax>
+                       <parameter name="data" required="true" />
+               </syntax>
+               <description>
+                       <para>Returns <literal>1</literal> if NULL or <literal>0</literal> otherwise.</para>
+               </description>
+       </function>
+       <function name="SET" language="en_US">
+               <synopsis>
+                       SET assigns a value to a channel variable.
+               </synopsis>
+               <syntax argsep="=">
+                       <parameter name="varname" required="true" />
+                       <parameter name="value" />
+               </syntax>
+               <description>
+               </description>
+       </function>
+       <function name="EXISTS" language="en_US">
+               <synopsis>
+                       Test the existence of a value.
+               </synopsis>
+               <syntax>
+                       <parameter name="data" required="true" />
+               </syntax>
+               <description>
+                       <para>Returns <literal>1</literal> if exists, <literal>0</literal> otherwise.</para>
+               </description>
+       </function>
+       <function name="IF" language="en_US">
+               <synopsis>
+                       Check for an expresion.
+               </synopsis>
+               <syntax argsep="?">
+                       <parameter name="expresion" required="true" />
+                       <parameter name="retvalue" argsep=":" required="true">
+                               <argument name="true" />
+                               <argument name="false" />
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Returns the data following <literal>?</literal> if true, else the data following <literal>:</literal></para>
+               </description>  
+       </function>
+       <function name="IFTIME" language="en_US">
+               <synopsis>
+                       Temporal Conditional.
+               </synopsis>
+               <syntax argsep="?">
+                       <parameter name="timespec" required="true" />
+                       <parameter name="retvalue" required="true" argsep=":">
+                               <argument name="true" />
+                               <argument name="false" />
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Returns the data following <literal>?</literal> if true, else the data following <literal>:</literal></para>
+               </description>
+       </function>
+       <function name="IMPORT" language="en_US">
+               <synopsis>
+                       Retrieve the value of a variable from another channel.
+               </synopsis>
+               <syntax>
+                       <parameter name="channel" required="true" />
+                       <parameter name="variable" required="true" />
+               </syntax>
+               <description>
+               </description>
+       </function>
+ ***/
+
 static int isnull(struct ast_channel *chan, const char *cmd, char *data,
                  char *buf, size_t len)
 {
@@ -168,46 +245,31 @@ static int acf_import(struct ast_channel *chan, const char *cmd, char *data, cha
 
 static struct ast_custom_function isnull_function = {
        .name = "ISNULL",
-       .synopsis = "NULL Test: Returns 1 if NULL or 0 otherwise",
-       .syntax = "ISNULL(<data>)",
        .read = isnull,
 };
 
 static struct ast_custom_function set_function = {
        .name = "SET",
-       .synopsis = "SET assigns a value to a channel variable",
-       .syntax = "SET(<varname>=[<value>])",
        .read = set,
 };
 
 static struct ast_custom_function exists_function = {
        .name = "EXISTS",
-       .synopsis = "Existence Test: Returns 1 if exists, 0 otherwise",
-       .syntax = "EXISTS(<data>)",
        .read = exists,
 };
 
 static struct ast_custom_function if_function = {
        .name = "IF",
-       .synopsis =
-               "Conditional: Returns the data following '?' if true, else the data following ':'",
-       .syntax = "IF(<expr>?[<true>][:<false>])",
        .read = acf_if,
 };
 
 static struct ast_custom_function if_time_function = {
        .name = "IFTIME",
-       .synopsis =
-               "Temporal Conditional: Returns the data following '?' if true, else the data following ':'",
-       .syntax = "IFTIME(<timespec>?[<true>][:<false>])",
        .read = iftime,
 };
 
 static struct ast_custom_function import_function = {
        .name = "IMPORT",
-       .synopsis =
-               "Retrieve the value of a variable from another channel\n",
-       .syntax = "IMPORT(channel,variable)",
        .read = acf_import,
 };
 
index 3517b16ed186be54f5ef3eaaa2b101f5ba609944..627cf860a5cc236ae8d91483ac61bff9557a9464 100644 (file)
@@ -39,6 +39,35 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/app.h"
 #include "asterisk/config.h"
 
+/*** DOCUMENTATION
+       <function name="MATH" language="en_US">
+               <synopsis>
+                       Performs Mathematical Functions.
+               </synopsis>
+               <syntax>
+                       <parameter name="expression" required="true">
+                               <para>Is of the form:
+                               <replaceable>number1</replaceable><replaceable>op</replaceable><replaceable>number2</replaceable>
+                               where the possible values for <replaceable>op</replaceable>
+                               are:</para>
+                               <para>+,-,/,*,%,&lt;&lt;,&gt;&gt;,^,AND,OR,XOR,&lt;,%gt;,&gt;=,&lt;=,== (and behave as their C equivalents)</para>
+                       </parameter>
+                       <parameter name="type">
+                               <para>Wanted type of result:</para>
+                               <para>f, float - float(default)</para>
+                               <para>i, int - integer</para>
+                               <para>h, hex - hex</para>
+                               <para>c, char - char</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Performs mathematicas functions based on two parameters and a operator, the returned
+                       value type is <replaceable>type</replaceable></para>
+                       <para>Example: Set(i=${MATH(123%16,int)}) - sets var i=11</para>
+               </description>
+       </function>
+ ***/
+
 enum TypeOfFunctions {
        ADDFUNCTION,
        DIVIDEFUNCTION,
@@ -306,17 +335,6 @@ static int math(struct ast_channel *chan, const char *cmd, char *parse,
 
 static struct ast_custom_function math_function = {
        .name = "MATH",
-       .synopsis = "Performs Mathematical Functions",
-       .syntax = "MATH(<number1><op><number2>[,<type_of_result>])",
-       .desc = "Perform calculation on number1 to number2. Valid ops are: \n"
-               "    +,-,/,*,%,<<,>>,^,AND,OR,XOR,<,>,>=,<=,==\n"
-               "and behave as their C equivalents.\n"
-               "<type_of_result> - wanted type of result:\n"
-               "       f, float - float(default)\n"
-               "       i, int - integer,\n"
-               "       h, hex - hex,\n"
-               "       c, char - char\n"
-               "Example: Set(i=${MATH(123%16,int)}) - sets var i=11",
        .read = math
 };
 
index b376e8ae34266ac025a681086e02fe893a6e2732..23b35489a7df6ef09efa871dea07357533695d46 100644 (file)
@@ -33,6 +33,20 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/module.h"
 #include "asterisk/pbx.h"
 
+/*** DOCUMENTATION
+       <function name="MD5" language="en_US">
+               <synopsis>
+                       Computes an MD5 digest.
+               </synopsis>
+               <syntax>
+                       <parameter name="data" required="true" />
+               </syntax>
+               <description>
+                       <para>Computes an MD5 digest.</para>
+               </description>
+       </function>
+ ***/
+
 static int md5(struct ast_channel *chan, const char *cmd, char *data,
               char *buf, size_t len)
 {
@@ -49,8 +63,6 @@ static int md5(struct ast_channel *chan, const char *cmd, char *data,
 
 static struct ast_custom_function md5_function = {
        .name = "MD5",
-       .synopsis = "Computes an MD5 digest",
-       .syntax = "MD5(<data>)",
        .read = md5,
 };
 
index 8b23263861a3a5c9e7e7cbe726b64c6477894291..a7cf731641a0ba2ac0307e44589265e09c8fe299 100644 (file)
@@ -28,6 +28,24 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/module.h"
 #include "asterisk/pbx.h"
 
+/*** DOCUMENTATION
+       <function name="IFMODULE" language="en_US">
+               <synopsis>
+                       Checks if an Asterisk module is loaded in memory.
+               </synopsis>
+               <syntax>
+                       <parameter name="modulename.so" required="true">
+                               <para>Module name complete with <literal>.so</literal></para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Checks if a module is loaded. Use the full module name
+                       as shown by the list in <literal>module list</literal>.
+                       Returns <literal>1</literal> if module exists in memory, otherwise <literal>0</literal></para>
+               </description>
+       </function>
+ ***/
+
 static int ifmodule_read(struct ast_channel *chan, const char *cmd, char *data,
                    char *buf, size_t len)
 {
@@ -46,12 +64,7 @@ static int ifmodule_read(struct ast_channel *chan, const char *cmd, char *data,
 
 static struct ast_custom_function ifmodule_function = {
        .name = "IFMODULE",
-       .synopsis = "Checks if an Asterisk module is loaded in memory",
-       .syntax = "IFMODULE(<modulename.so>)",
        .read = ifmodule_read,
-       .desc = "Checks if a module is loaded. Use the full module name\n"
-               "as shown by the list in \"module list\". \n"
-               "Returns \"1\" if module exists in memory, otherwise \"0\".\n",
 };
 
 
index 85f7e239533604e40a6368b4b47589430a341c9e..135dd9819603a97a4e4132b16c73c85939e30d4c 100644 (file)
@@ -47,6 +47,58 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/app.h"
 #include "asterisk/cli.h"
 
+/*** DOCUMENTATION
+       <function name="ODBC_FETCH" language="en_US">
+               <synopsis>
+                       Fetch a row from a multirow query.
+               </synopsis>
+               <syntax>
+                       <parameter name="result-id" required="true" />
+               </syntax>
+               <description>
+                       <para>For queries which are marked as mode=multirow, the original 
+                       query returns a <replaceable>result-id</replaceable> from which results 
+                       may be fetched.  This function implements the actual fetch of the results.</para>
+                       <para>This also sets <variable>ODBC_FETCH_STATUS</variable>.</para>
+                       <variablelist>
+                               <variable name="ODBC_FETCH_STATUS">
+                                       <value name="SUCESS">
+                                               If rows are available.
+                                       </value>
+                                       <value name="FAILURE">
+                                               If no rows are available.
+                                       </value>
+                               </variable>
+                       </variablelist>
+               </description>
+       </function>
+       <application name="ODBCFinish" language="en_US">
+               <synopsis>
+                       Clear the resultset of a sucessful multirow query.
+               </synopsis>
+               <syntax>
+                       <parameter name="result-id" required="true" />
+               </syntax>
+               <description>
+                       <para>For queries which are marked as mode=multirow, this will clear 
+                       any remaining rows of the specified resultset.</para>
+               </description>
+       </application>
+       <function name="SQL_ESC" language="en_US">
+               <synopsis>
+                       Escapes single ticks for use in SQL statements.
+               </synopsis>
+               <syntax>
+                       <parameter name="string" required="true" />
+               </syntax>
+               <description>
+                       <para>Used in SQL templates to escape data which may contain single ticks 
+                       <literal>'</literal> which are otherwise used to delimit data.</para>
+                       <para>Example: SELECT foo FROM bar WHERE baz='${SQL_ESC(${ARG1})}'</para>
+               </description>
+       </function>
+ ***/
+
 static char *config = "func_odbc.conf";
 
 enum {
@@ -620,12 +672,6 @@ static int acf_escape(struct ast_channel *chan, const char *cmd, char *data, cha
 
 static struct ast_custom_function escape_function = {
        .name = "SQL_ESC",
-       .synopsis = "Escapes single ticks for use in SQL statements",
-       .syntax = "SQL_ESC(<string>)",
-       .desc =
-"Used in SQL templates to escape data which may contain single ticks (') which\n"
-"are otherwise used to delimit data.  For example:\n"
-"SELECT foo FROM bar WHERE baz='${SQL_ESC(${ARG1})}'\n",
        .read = acf_escape,
        .write = NULL,
 };
@@ -660,24 +706,11 @@ static int acf_fetch(struct ast_channel *chan, const char *cmd, char *data, char
 
 static struct ast_custom_function fetch_function = {
        .name = "ODBC_FETCH",
-       .synopsis = "Fetch a row from a multirow query",
-       .syntax = "ODBC_FETCH(<result-id>)",
-       .desc =
-"For queries which are marked as mode=multirow, the original query returns a\n"
-"result-id from which results may be fetched.  This function implements the\n"
-"actual fetch of the results.\n"
-"This function also sets ODBC_FETCH_STATUS to one of \"SUCCESS\" or \"FAILURE\",\n"
-"depending upon whether there were rows available or not.\n",
        .read = acf_fetch,
        .write = NULL,
 };
 
 static char *app_odbcfinish = "ODBCFinish";
-static char *syn_odbcfinish = "Clear the resultset of a successful multirow query";
-static char *desc_odbcfinish =
-"ODBCFinish(<result-id>)\n"
-"  Clears any remaining rows of the specified resultset\n";
-
 
 static int exec_odbcfinish(struct ast_channel *chan, void *data)
 {
@@ -784,6 +817,12 @@ static int init_acf_query(struct ast_config *cfg, char *catg, struct acf_odbc_qu
                *query = NULL;
                return ENOMEM;
        }
+       if (ast_string_field_init((*query)->acf, 128)) {
+               ast_free((*query)->acf);
+               ast_free(*query);
+               *query = NULL;
+               return ENOMEM;
+       }
 
        if ((tmp = ast_variable_retrieve(cfg, catg, "prefix")) && !ast_strlen_zero(tmp)) {
                asprintf((char **)&((*query)->acf->name), "%s_%s", tmp, catg);
@@ -792,6 +831,7 @@ static int init_acf_query(struct ast_config *cfg, char *catg, struct acf_odbc_qu
        }
 
        if (!((*query)->acf->name)) {
+               ast_string_field_free_memory((*query)->acf);
                ast_free((*query)->acf);
                ast_free(*query);
                *query = NULL;
@@ -799,13 +839,14 @@ static int init_acf_query(struct ast_config *cfg, char *catg, struct acf_odbc_qu
        }
 
        if ((tmp = ast_variable_retrieve(cfg, catg, "syntax")) && !ast_strlen_zero(tmp)) {
-               asprintf((char **)&((*query)->acf->syntax), "%s(%s)", (*query)->acf->name, tmp);
+               ast_string_field_build((*query)->acf, syntax, "%s(%s)", (*query)->acf->name, tmp);
        } else {
-               asprintf((char **)&((*query)->acf->syntax), "%s(<arg1>[...[,<argN>]])", (*query)->acf->name);
+               ast_string_field_build((*query)->acf, syntax, "%s(<arg1>[...[,<argN>]])", (*query)->acf->name);
        }
 
-       if (!((*query)->acf->syntax)) {
+       if (ast_strlen_zero((*query)->acf->syntax)) {
                ast_free((char *)(*query)->acf->name);
+               ast_string_field_free_memory((*query)->acf);
                ast_free((*query)->acf);
                ast_free(*query);
                *query = NULL;
@@ -813,14 +854,14 @@ static int init_acf_query(struct ast_config *cfg, char *catg, struct acf_odbc_qu
        }
 
        if ((tmp = ast_variable_retrieve(cfg, catg, "synopsis")) && !ast_strlen_zero(tmp)) {
-               (*query)->acf->synopsis = ast_strdup(tmp);
+               ast_string_field_set((*query)->acf, synopsis, tmp);
        } else {
-               (*query)->acf->synopsis = ast_strdup("Runs the referenced query with the specified arguments");
+               ast_string_field_set((*query)->acf, synopsis, "Runs the referenced query with the specified arguments");
        }
 
-       if (!((*query)->acf->synopsis)) {
+       if (ast_strlen_zero((*query)->acf->synopsis)) {
                ast_free((char *)(*query)->acf->name);
-               ast_free((char *)(*query)->acf->syntax);
+               ast_string_field_free_memory((*query)->acf);
                ast_free((*query)->acf);
                ast_free(*query);
                *query = NULL;
@@ -828,7 +869,7 @@ static int init_acf_query(struct ast_config *cfg, char *catg, struct acf_odbc_qu
        }
 
        if (!ast_strlen_zero((*query)->sql_read) && !ast_strlen_zero((*query)->sql_write)) {
-               asprintf((char **)&((*query)->acf->desc),
+               ast_string_field_build((*query)->acf, desc,
                                        "Runs the following query, as defined in func_odbc.conf, performing\n"
                                        "substitution of the arguments into the query as specified by ${ARG1},\n"
                                        "${ARG2}, ... ${ARGn}.  When setting the function, the values are provided\n"
@@ -844,13 +885,13 @@ static int init_acf_query(struct ast_config *cfg, char *catg, struct acf_odbc_qu
                                        ast_strlen_zero((*query)->sql_insert) ? "" : (*query)->sql_insert,
                                        ast_strlen_zero((*query)->sql_insert) ? "" : "\n");
        } else if (!ast_strlen_zero((*query)->sql_read)) {
-               asprintf((char **)&((*query)->acf->desc),
-                                       "Runs the following query, as defined in func_odbc.conf, performing\n"
-                                       "substitution of the arguments into the query as specified by ${ARG1},\n"
-                                       "${ARG2}, ... ${ARGn}.  This function may only be read, not set.\n\nSQL:\n%s\n",
-                                       (*query)->sql_read);
+               ast_string_field_build((*query)->acf, desc,
+                                               "Runs the following query, as defined in func_odbc.conf, performing\n"
+                                               "substitution of the arguments into the query as specified by ${ARG1},\n"
+                                               "${ARG2}, ... ${ARGn}.  This function may only be read, not set.\n\nSQL:\n%s\n",
+                                               (*query)->sql_read);
        } else if (!ast_strlen_zero((*query)->sql_write)) {
-               asprintf((char **)&((*query)->acf->desc),
+               ast_string_field_build((*query)->acf, desc,     
                                        "Runs the following query, as defined in func_odbc.conf, performing\n"
                                        "substitution of the arguments into the query as specified by ${ARG1},\n"
                                        "${ARG2}, ... ${ARGn}.  The values are provided either in whole as\n"
@@ -864,8 +905,7 @@ static int init_acf_query(struct ast_config *cfg, char *catg, struct acf_odbc_qu
                                        ast_strlen_zero((*query)->sql_insert) ? "" : (*query)->sql_insert,
                                        ast_strlen_zero((*query)->sql_insert) ? "" : "\n");
        } else {
-               ast_free((char *)(*query)->acf->synopsis);
-               ast_free((char *)(*query)->acf->syntax);
+               ast_string_field_free_memory((*query)->acf);
                ast_free((char *)(*query)->acf->name);
                ast_free((*query)->acf);
                ast_free(*query);
@@ -873,9 +913,8 @@ static int init_acf_query(struct ast_config *cfg, char *catg, struct acf_odbc_qu
                return EINVAL;
        }
 
-       if (! ((*query)->acf->desc)) {
-               ast_free((char *)(*query)->acf->synopsis);
-               ast_free((char *)(*query)->acf->syntax);
+       if (ast_strlen_zero((*query)->acf->desc)) {
+               ast_string_field_free_memory((*query)->acf);
                ast_free((char *)(*query)->acf->name);
                ast_free((*query)->acf);
                ast_free(*query);
@@ -904,12 +943,7 @@ static int free_acf_query(struct acf_odbc_query *query)
                if (query->acf) {
                        if (query->acf->name)
                                ast_free((char *)query->acf->name);
-                       if (query->acf->syntax)
-                               ast_free((char *)query->acf->syntax);
-                       if (query->acf->synopsis)
-                               ast_free((char *)query->acf->synopsis);
-                       if (query->acf->desc)
-                               ast_free((char *)query->acf->desc);
+                       ast_string_field_free_memory(query->acf);
                        ast_free(query->acf);
                }
                ast_free(query);
@@ -1254,7 +1288,7 @@ static int load_module(void)
        struct ast_flags config_flags = { 0 };
 
        res |= ast_custom_function_register(&fetch_function);
-       res |= ast_register_application(app_odbcfinish, exec_odbcfinish, syn_odbcfinish, desc_odbcfinish);
+       res |= ast_register_application_xml(app_odbcfinish, exec_odbcfinish);
        AST_RWLIST_WRLOCK(&queries);
 
        cfg = ast_config_load(config, config_flags);
index a3db21d26b0b761d86ae71b33086a7ea9c456f2d..079723686fe49dd55be1b6669c5ad9107caf0f98 100644 (file)
@@ -34,6 +34,24 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/utils.h"
 #include "asterisk/app.h"
 
+/*** DOCUMENTATION
+       <function name="RAND" language="en_US">
+               <synopsis>
+                       Choose a random number in a range.                      
+               </synopsis>
+               <syntax>
+                       <parameter name="min" />
+                       <parameter name="max" />
+               </syntax>
+               <description>
+                       <para>Choose a random number between <replaceable>min</replaceable> and <replaceable>max</replaceable>. 
+                       <replaceable>min</replaceable> defaults to <literal>0</literal>, if not specified, while <replaceable>max</replaceable> defaults 
+                       to <literal>RAND_MAX</literal> (2147483647 on many systems).</para>
+                       <para>Example:  Set(junky=${RAND(1,8)});
+                       Sets junky to a random number between 1 and 8, inclusive.</para>
+               </description>
+       </function>
+ ***/
 static int acf_rand_exec(struct ast_channel *chan, const char *cmd,
                         char *parse, char *buffer, size_t buflen)
 {
@@ -68,13 +86,6 @@ static int acf_rand_exec(struct ast_channel *chan, const char *cmd,
 
 static struct ast_custom_function acf_rand = {
        .name = "RAND",
-       .synopsis = "Choose a random number in a range",
-       .syntax = "RAND([min][,max])",
-       .desc =
-               "Choose a random number between min and max.  Min defaults to 0, if not\n"
-               "specified, while max defaults to RAND_MAX (2147483647 on many systems).\n"
-               "  Example:  Set(junky=${RAND(1,8)}); \n"
-               "  Sets junky to a random number between 1 and 8, inclusive.\n",
        .read = acf_rand_exec,
 };
 
index f3dd14be68dbe8f90b0fbe977f153af6f9bc1df8..31989c42590d7d508afa6785a5ebf3ab54fd375e 100644 (file)
@@ -37,6 +37,72 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/utils.h"
 #include "asterisk/app.h"
 
+/*** DOCUMENTATION
+       <function name="REALTIME" language="en_US">
+               <synopsis>
+                       RealTime Read/Write Functions.
+               </synopsis>
+               <syntax>
+                       <parameter name="family" required="true" />
+                       <parameter name="fieldmatch" required="true" />
+                       <parameter name="value" />
+                       <parameter name="delim1|field">
+                               <para>Use <replaceable>delim1</replaceable> with <replaceable>delim2</replaceable> on
+                               read and <replaceable>field</replaceable> without <replaceable>delim2</replaceable> on
+                               write</para>
+                               <para>If we are reading and <replaceable>delim1</replaceable> is not specified, defaults
+                               to <literal>,</literal></para>
+                       </parameter>
+                       <parameter name="delim2">
+                               <para>Parameter only used when reading, if not specified defaults to <literal>=</literal></para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>This function will read or write values from/to a RealTime repository.
+                       REALTIME(....) will read names/values from the repository, and 
+                       REALTIME(....)= will write a new value/field to the repository. On a
+                       read, this function returns a delimited text string. The name/value
+                       pairs are delimited by <replaceable>delim1</replaceable>, and the name and value are delimited
+                       between each other with delim2. 
+                       If there is no match, NULL will be returned by the function.
+                       On a write, this function will always return NULL.</para>
+               </description>
+       </function>
+       <function name="REALTIME_STORE" language="en_US">
+               <synopsis>
+                       RealTime Store Function.
+               </synopsis>
+               <syntax>
+                       <parameter name="family" required="true" />
+                       <parameter name="field1" required="true" />
+                       <parameter name="fieldN" required="true" multiple="true" />
+                       <parameter name="field30" required="true" />
+               </syntax>
+               <description>
+                       <para>This function will insert a new set of values into the RealTime repository.
+                       If RT engine provides an unique ID of the stored record, REALTIME_STORE(...)=..
+                       creates channel variable named RTSTOREID, which contains value of unique ID.
+                       Currently, a maximum of 30 field/value pairs is supported.</para>
+               </description>
+       </function>
+       <function name="REALTIME_DESTROY" language="en_US">
+               <synopsis>
+                       RealTime Destroy Function.
+               </synopsis>
+               <syntax>
+                       <parameter name="family" required="true" />
+                       <parameter name="fieldmatch" required="true" />
+                       <parameter name="value" />
+                       <parameter name="delim1" />
+                       <parameter name="delim2" />
+               </syntax>
+               <description>
+                       <para>This function acts in the same way as REALTIME(....) does, except that
+                       it destroys matched record in RT engine.</para>
+               </description>
+       </function>
+ ***/
+
 static int function_realtime_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) 
 {
        struct ast_variable *var, *head;
@@ -232,39 +298,17 @@ static int function_realtime_readdestroy(struct ast_channel *chan, const char *c
 
 struct ast_custom_function realtime_function = {
        .name = "REALTIME",
-       .synopsis = "RealTime Read/Write Functions",
-       .syntax = "REALTIME(family,fieldmatch[,value[,delim1[,delim2]]]) on read\n"
-                 "REALTIME(family,fieldmatch,value,field) on write",
-       .desc = "This function will read or write values from/to a RealTime repository.\n"
-               "REALTIME(....) will read names/values from the repository, and \n"
-               "REALTIME(....)= will write a new value/field to the repository. On a\n"
-               "read, this function returns a delimited text string. The name/value \n"
-               "pairs are delimited by delim1, and the name and value are delimited \n"
-               "between each other with delim2. The default for delim1 is ',' and   \n"
-               "the default for delim2 is '='. If there is no match, NULL will be   \n"
-               "returned by the function. On a write, this function will always     \n"
-               "return NULL. \n",
        .read = function_realtime_read,
        .write = function_realtime_write,
 };
 
 struct ast_custom_function realtime_store_function = {
        .name = "REALTIME_STORE",
-       .synopsis = "RealTime Store Function",
-       .syntax = "REALTIME_STORE(family,field1,field2,...,field30) = value1,value2,...,value30",
-       .desc = "This function will insert a new set of values into the RealTime repository.\n"
-               "If RT engine provides an unique ID of the stored record, REALTIME_STORE(...)=..\n"
-               "creates channel variable named RTSTOREID, which contains value of unique ID.\n"
-               "Currently, a maximum of 30 field/value pairs is supported.\n",
        .write = function_realtime_store,
 };
 
 struct ast_custom_function realtime_destroy_function = {
        .name = "REALTIME_DESTROY",
-       .synopsis = "RealTime Destroy Function",
-       .syntax = "REALTIME_DESTROY(family,fieldmatch[,value[,delim1[,delim2]]])\n",
-       .desc = "This function acts in the same way as REALTIME(....) does, except that\n"
-               "it destroys matched record in RT engine.\n",
        .read = function_realtime_readdestroy,
 };
 
index 6474140dd59699d4ed4e3a498691e864542d2c0b..973bc5c07a05926d21846197fe681a1830f36d3c 100644 (file)
@@ -31,6 +31,25 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/module.h"
 #include "asterisk/pbx.h"
 
+/*** DOCUMENTATION
+       <function name="SHA1" language="en_US">
+               <synopsis>
+                       Computes a SHA1 digest.
+               </synopsis>
+               <syntax>
+                       <parameter name="data" required="true">
+                               <para>Input string</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Generate a SHA1 digest via the SHA1 algorythm.</para>
+                       <para>Example:  Set(sha1hash=${SHA1(junky)})</para>
+                       <para>Sets the asterisk variable sha1hash to the string <literal>60fa5675b9303eb62f99a9cd47f9f5837d18f9a0</literal>
+                       which is known as his hash</para>       
+               </description>
+       </function>
+ ***/
+
 static int sha1(struct ast_channel *chan, const char *cmd, char *data,
                char *buf, size_t len)
 {
@@ -54,13 +73,7 @@ static int sha1(struct ast_channel *chan, const char *cmd, char *data,
 
 static struct ast_custom_function sha1_function = {
        .name = "SHA1",
-       .synopsis = "Computes a SHA1 digest",
-       .syntax = "SHA1(<data>)",
        .read = sha1,
-       .desc = "Generate a SHA1 digest via the SHA1 algorythm.\n"
-               " Example:  Set(sha1hash=${SHA1(junky)})\n"
-               " Sets the asterisk variable sha1hash to the string '60fa5675b9303eb62f99a9cd47f9f5837d18f9a0'\n"
-               " which is known as his hash\n",
 };
 
 static int unload_module(void)
index 57a9819cd3e1b0d26e5fcb1ca4f8ba2d5345e881..df7164d5f519acb422b68d881316ecaaaa4eb464 100644 (file)
@@ -63,19 +63,31 @@ static int shell_helper(struct ast_channel *chan, const char *cmd, char *data,
        return 0;
 }
 
+/*** DOCUMENTATION
+       <function name="SHELL" language="en_US">
+               <synopsis>
+                       Executes a command as if you were at a shell.
+               </synopsis>
+               <syntax>
+                       <parameter name="command" required="true">
+                               <para>This is the argument to the function, the command you want to pass to the shell.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Returns the value from a system command</para>
+                       <para>Example:  <literal>Set(foo=${SHELL(echo \bar\)})</literal></para>
+                       <note><para>When using the SHELL() dialplan function, your \SHELL\ is /bin/sh,
+                       which may differ as to the underlying shell, depending upon your production
+                       platform.  Also keep in mind that if you are using a common path, you should
+                       be mindful of race conditions that could result from two calls running
+                       SHELL() simultaneously.</para></note>
+               </description>
+       </function>
+ ***/
 static struct ast_custom_function shell_function = {
        .name = "SHELL",
-       .synopsis = "Executes a command as if you were at a shell.",
-       .syntax = "SHELL(<command>)",
        .read = shell_helper,
-       .desc =
-"Returns the value from a system command\n"
-"  Example:  Set(foo=${SHELL(echo \"bar\")})\n"
-"  Note:  When using the SHELL() dialplan function, your \"SHELL\" is /bin/sh,\n"
-"  which may differ as to the underlying shell, depending upon your production\n"
-"  platform.  Also keep in mind that if you are using a common path, you should\n"
-"  be mindful of race conditions that could result from two calls running\n"
-"  SHELL() simultaneously.\n",
 };
 
 static int unload_module(void)
index 4ddfab80b1d134214a5624b29cc7c9db19dd7443..6858cf7a306a255192fc0e2b8075af1d87a5ca41 100644 (file)
@@ -48,6 +48,52 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
 #define DEFAULT_AGC_LEVEL 8000.0
 
+/*** DOCUMENTATION
+       <function name="AGC" language="en_US">
+               <synopsis>
+                       Apply automatic gain control to audio on a channel.
+               </synopsis>
+               <syntax>
+                       <parameter name="channeldirection" required="true">
+                               <para>This can be either <literal>rx</literal> or <literal>tx</literal></para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>The AGC function will apply automatic gain control to the audio on the
+                       channel that it is executed on. Using <literal>rx</literal> for audio recieved
+                       and <literal>tx</literal> for audio transmitted to the channel. When using this
+                       function you set a target audio level. It is primarly intended for use with
+                       analog lines, but could be useful for other channels as well. The target volume 
+                       is set with a number between <literal>1-32768</literal>. The larger the number
+                       the louder (more gain) the channel will recieve.</para>
+                       <para>Examples:</para>
+                       <para>exten => 1,1,Set(AGC(rx)=8000)</para>
+                       <para>exten => 1,2,Set(AGC(tx)=off)</para>
+               </description>
+       </function>
+       <function name="DENOISE" language="en_US">
+               <synopsis>
+                       Apply noise reduction to audio on a channel.
+               </synopsis>
+               <syntax>
+                       <parameter name="channeldirection" required="true">
+                               <para>This can be either <literal>rx</literal> or <literal>tx</literal> 
+                               the values that can be set to this are either <literal>on</literal> and
+                               <literal>off</literal></para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>The DENOISE function will apply noise reduction to audio on the channel
+                       that it is executed on. It is very useful for noisy analog lines, especially
+                       when adjusting gains or using AGC. Use <literal>rx</literal> for audio received from the channel
+                       and <literal>tx</literal> to apply the filter to the audio being sent to the channel.</para>
+                       <para>Examples:</para>
+                       <para>exten => 1,1,Set(DENOISE(rx)=on)</para>
+                       <para>exten => 1,2,Set(DENOISE(tx)=off)</para>
+               </description>
+       </function>
+ ***/
+
 struct speex_direction_info {
        SpeexPreprocessState *state;    /*!< speex preprocess state object */
        int agc;                                                /*!< audio gain control is enabled or not */
@@ -290,39 +336,12 @@ static int speex_read(struct ast_channel *chan, const char *cmd, char *data, cha
 
 static struct ast_custom_function agc_function = {
        .name = "AGC",
-       .synopsis = "Apply automatic gain control to audio on a channel",
-       .desc =
-       "  The AGC function will apply automatic gain control to audio on the channel\n"
-       "that this function is executed on.  Use rx for audio received from the channel\n"
-       "and tx to apply AGC to the audio being sent to the channel.  When using this\n"
-       "function, you set a target audio level.  It is primarily intended for use with\n"
-       "analog lines, but could be useful for other channels, as well.  The target volume\n"
-       "is set with a number between 1 and 32768.  Larger numbers are louder.\n"
-       "  Example Usage:\n"
-       "    Set(AGC(rx)=8000)\n"
-       "    Set(AGC(tx)=8000)\n"
-       "    Set(AGC(rx)=off)\n"
-       "    Set(AGC(tx)=off)\n"
-       "",
        .write = speex_write,
        .read = speex_read
 };
 
 static struct ast_custom_function denoise_function = {
        .name = "DENOISE",
-       .synopsis = "Apply noise reduction to audio on a channel",
-       .desc =
-       "  The DENOISE function will apply noise reduction to audio on the channel\n"
-       "that this function is executed on.  It is especially useful for noisy analog\n"
-       "lines, especially when adjusting gains or using AGC.  Use rx for audio\n"
-       "received from the channel and tx to apply the filter to the audio being sent\n"
-       "to the channel.\n"
-       "  Example Usage:\n"
-       "    Set(DENOISE(rx)=on)\n"
-       "    Set(DENOISE(tx)=on)\n"
-       "    Set(DENOISE(rx)=off)\n"
-       "    Set(DENOISE(tx)=off)\n"
-       "",
        .write = speex_write,
        .read = speex_read
 };
index 2494518e3cc5a4d414ce5192a9781d6e4b06b2eb..c456385648ce033f1d38d0022b55dba6bdf25350 100644 (file)
@@ -39,6 +39,244 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/app.h"
 #include "asterisk/localtime.h"
 
+/*** DOCUMENTATION
+       <function name="FIELDQTY" language="en_US">
+               <synopsis>
+                       Count the fields with an arbitrary delimiter
+               </synopsis>
+               <syntax>
+                       <parameter name="varname" required="true" />
+                       <parameter name="delim" required="true" />
+               </syntax>
+               <description>
+                       <para>Example: ${FIELDQTY(ex-amp-le,-)} returns 3</para>
+               </description>
+       </function>
+       <function name="FILTER" language="en_US">
+               <synopsis>
+                       Filter the string to include only the allowed characters
+               </synopsis>
+               <syntax>
+                       <parameter name="allowed-chars" required="true" />
+                       <parameter name="string" required="true" />
+               </syntax>
+               <description>
+                       <para>Permits all characters listed in <replaceable>allowed-chars</replaceable>, 
+                       filtering all others outs. In addition to literally listing the characters, 
+                       you may also use ranges of characters (delimited by a <literal>-</literal></para>
+                       <para>Hexadecimal characters started with a <literal>\x</literal>(i.e. \x20)</para>
+                       <para>Octal characters started with a <literal>\0</literal> (i.e. \040)</para>
+                       <para>Also <literal>\t</literal>,<literal>\n</literal> and <literal>\r</literal> are recognized.</para> 
+                       <note><para>If you want the <literal>-</literal> character it needs to be prefixed with a 
+                       <literal>\</literal></para></note>
+               </description>
+       </function>
+       <function name="REGEX" language="en_US">
+               <synopsis>
+                       Check string against a regular expression.
+               </synopsis>
+               <syntax argsep=" ">
+                       <parameter name="&quot;regular expression&quot;" required="true" />
+                       <parameter name="string" required="true" />
+               </syntax>
+               <description>
+                       <para>Return <literal>1</literal> on regular expression match or <literal>0</literal> otherwise</para>
+                       <para>Please note that the space following the double quotes separating the 
+                       regex from the data is optional and if present, is skipped. If a space is 
+                       desired at the beginning of the data, then put two spaces there; the second 
+                       will not be skipped.</para>
+               </description>
+       </function>
+       <application name="ClearHash" language="en_US">
+               <synopsis>
+                       Clear the keys from a specified hashname.
+               </synopsis>
+               <syntax>
+                       <parameter name="hashname" required="true" />
+               </syntax>
+               <description>
+                       <para>Clears all keys out of the specified <replaceable>hashname</replaceable>.</para>
+               </description>
+       </application>
+       <function name="HASH" language="en_US">
+               <synopsis>
+                       Implementation of a dialplan associative array
+               </synopsis>
+               <syntax>
+                       <parameter name="hashname" required="true" />
+                       <parameter name="hashkey" />
+               </syntax>
+               <description>
+                       <para>In two arguments mode, gets and sets values to corresponding keys within
+                       a named associative array. The single-argument mode will only work when assigned
+                       to from a function defined by func_odbc</para>
+               </description>
+       </function>
+       <function name="HASHKEYS" language="en_US">
+               <synopsis>
+                       Retrieve the keys of the HASH() function.
+               </synopsis>
+               <syntax>
+                       <parameter name="hashname" required="true" />
+               </syntax>
+               <description>
+                       <para>Returns a comma-delimited list of the current keys of the associative array 
+                       defined by the HASH() function. Note that if you iterate over the keys of 
+                       the result, adding keys during iteration will cause the result of the HASHKEYS()
+                       function to change.</para>
+               </description>
+       </function>
+       <function name="KEYPADHASH" language="en_US">
+               <synopsis>
+                       Hash the letters in string into equivalent keypad numbers.
+               </synopsis>
+               <syntax>
+                       <parameter name="string" required="true" />
+               </syntax>
+               <description>
+                       <para>Example: ${KEYPADHASH(Les)} returns "537"</para>
+               </description>
+       </function>
+       <function name="ARRAY" language="en_US">
+               <synopsis>
+                       Allows setting multiple variables at once.
+               </synopsis>
+               <syntax>
+                       <parameter name="var1" required="true" />
+                       <parameter name="var2" required="false" multiple="true" />
+                       <parameter name="varN" required="false" />
+               </syntax>
+               <description>
+                       <para>The comma-delimited list passed as a value to which the function is set will 
+                       be interpreted as a set of values to which the comma-delimited list of 
+                       variable names in the arguement should be set.</para>
+                       <para>Example: Set(ARRAY(var1,var2)=1,2) will set var1 to 1 and var2 to 2</para>
+               </description>
+       </function>
+       <function name="STRPTIME" language="en_US">
+               <synopsis>
+                       Returns the epoch of the arbitrary date/time string structured as described by the format.
+               </synopsis>
+               <syntax>
+                       <parameter name="datetime" required="true" />
+                       <parameter name="timezone" required="true" />
+                       <parameter name="format" required="true" />
+               </syntax>
+               <description>
+                       <para>This is useful for converting a date into <literal>EPOCH</literal> time, 
+                       possibly to pass to an application like SayUnixTime or to calculate the difference
+                       between the two date strings</para>
+                       <para>Example: ${STRPTIME(2006-03-01 07:30:35,America/Chicago,%Y-%m-%d %H:%M:%S)} returns 1141219835</para>
+               </description>
+       </function>
+       <function name="STRFTIME" language="en_US">
+               <synopsis>
+                       Returns the current date/time in the specified format.
+               </synopsis>
+               <syntax>
+                       <parameter name="epoch" />
+                       <parameter name="timezone" />
+                       <parameter name="format" />
+               </syntax>
+               <description>
+                       <para>STRFTIME supports all of the same formats as the underlying C function
+                       <emphasis>strftime(3)</emphasis>.
+                       It also supports the following format: <literal>%[n]q</literal> - fractions of a second,
+                       with leading zeros.</para>
+                       <para>Example: <literal>%3q</literal> will give milliseconds and <literal>%1q</literal>
+                       will give tenths of a second. The default is set at milliseconds (n=3).
+                       The common case is to use it in combination with %S, as in <literal>%S.%3q</literal>.</para>
+               </description>
+               <see-also>
+                       <ref type="manpage">strftime(3)</ref>
+               </see-also>
+       </function>
+       <function name="EVAL" language="en_US">
+               <synopsis>
+                       Evaluate stored variables
+               </synopsis>
+               <syntax>
+                       <parameter name="variable" required="true" />
+               </syntax>
+               <description>
+                       <para>Using EVAL basically causes a string to be evaluated twice.
+                       When a variable or expression is in the dialplan, it will be
+                       evaluated at runtime. However, if the results of the evaluation
+                       is in fact another variable or expression, using EVAL will have it
+                       evaluated a second time.</para>
+                       <para>Example: If the <variable>MYVAR</variable> contains
+                       <variable>OTHERVAR</variable>, then the result of ${EVAL(
+                       <variable>MYVAR</variable>)} in the dialplan will be the
+                       contents of <variable>OTHERVAR</variable>. Normally just
+                       putting <variable>MYVAR</variable> in the dialplan the result
+                       would be <variable>OTHERVAR</variable>.</para>
+               </description>
+       </function>
+       <function name="TOUPPER" language="en_US">
+               <synopsis>
+                       Convert string to all uppercase letters.
+               </synopsis>
+               <syntax>
+                       <parameter name="string" required="true" />
+               </syntax>
+               <description>
+                       <para>Example: ${TOUPPER(Example)} returns "EXAMPLE"</para>
+               </description>
+       </function>
+       <function name="TOLOWER" language="en_US">
+               <synopsis>
+                       Convert string to all lowercase letters.
+               </synopsis>
+               <syntax>
+                       <parameter name="string" required="true" />
+               </syntax>
+               <description>
+                       <para>Example: ${TOLOWER(Example)} returns "example"</para>
+               </description>
+       </function>
+       <function name="LEN" language="en_US">
+               <synopsis>
+                       Return the length of the string given.
+               </synopsis>
+               <syntax>
+                       <parameter name="string" required="true" />
+               </syntax>
+               <description>
+                       <para>Example: ${LEN(example)} returns 7</para>
+               </description>
+       </function>
+       <function name="SPRINTF" language="en_US">
+               <synopsis>
+                       Format a variable according to a format string.
+               </synopsis>
+               <syntax>
+                       <parameter name="format" required="true" />
+                       <parameter name="arg1" required="true" />
+                       <parameter name="arg2" multiple="true" />
+                       <parameter name="argN" />
+               </syntax>
+               <description>
+                       <para>Parses the format string specified and returns a string matching 
+                       that format. Supports most options found in <emphasis>sprintf(3)</emphasis>.
+                       Returns a shortened string if a format specifier is not recognized.</para>
+               </description>
+               <see-also>
+                       <ref type="manpage">sprintf(3)</ref>
+               </see-also>
+       </function>
+       <function name="QUOTE" language="en_US">
+               <synopsis>
+                       Quotes a given string, escaping embedded quotes as necessary
+               </synopsis>
+               <syntax>
+                       <parameter name="string" required="true" />
+               </syntax>
+               <description>
+                       <para>Example: ${QUOTE(ab"c"de)} will return "abcde"</para>
+               </description>
+       </function>
+ ***/
+
 static int function_fieldqty(struct ast_channel *chan, const char *cmd,
                             char *parse, char *buf, size_t len)
 {
@@ -81,8 +319,6 @@ static int function_fieldqty(struct ast_channel *chan, const char *cmd,
 
 static struct ast_custom_function fieldqty_function = {
        .name = "FIELDQTY",
-       .synopsis = "Count the fields, with an arbitrary delimiter",
-       .syntax = "FIELDQTY(<varname>,<delim>)",
        .read = function_fieldqty,
 };
 
@@ -147,16 +383,7 @@ static int filter(struct ast_channel *chan, const char *cmd, char *parse, char *
 
 static struct ast_custom_function filter_function = {
        .name = "FILTER",
-       .synopsis = "Filter the string to include only the allowed characters",
-       .syntax = "FILTER(<allowed-chars>,<string>)",
        .read = filter,
-       .desc =
-"Permits all characters listed in <allowed-chars>, filtering all others out.\n"
-"In addition to literally listing the characters, you may also use ranges of\n"
-"characters (delimited by a '-'), as well as hexadecimal characters started\n"
-"with a \\x (i.e. \\x20) and octal characters started with \\0 (i.e. \\040).\n"
-"Also, \\t, \\n, and \\r are recognized.  If you want a literal '-' character,\n"
-"simply prefix it with a '\\'\n",
 };
 
 static int regex(struct ast_channel *chan, const char *cmd, char *parse, char *buf,
@@ -198,13 +425,6 @@ static int regex(struct ast_channel *chan, const char *cmd, char *parse, char *b
 
 static struct ast_custom_function regex_function = {
        .name = "REGEX",
-       .synopsis = "Regular Expression",
-       .desc =  
-               "Returns 1 if data matches regular expression, or 0 otherwise.\n"
-               "Please note that the space following the double quotes separating the regex from the data\n"
-               "is optional and if present, is skipped. If a space is desired at the beginning of the data,\n"
-               "then put two spaces there; the second will not be skipped.\n",
-       .syntax = "REGEX(\"<regular expression>\" <data>)",
        .read = regex,
 };
 
@@ -212,10 +432,6 @@ static struct ast_custom_function regex_function = {
 #define HASH_FORMAT    HASH_PREFIX "%s~"
 
 static char *app_clearhash = "ClearHash";
-static char *syn_clearhash = "Clear the keys from a specified hashname";
-static char *desc_clearhash =
-"ClearHash(<hashname>)\n"
-"  Clears all keys out of the specified hashname\n";
 
 /* This function probably should migrate to main/pbx.c, as pbx_builtin_clearvar_prefix() */
 static void clearvar_prefix(struct ast_channel *chan, const char *prefix)
@@ -400,38 +616,18 @@ static int hash_read(struct ast_channel *chan, const char *cmd, char *data, char
 
 static struct ast_custom_function hash_function = {
        .name = "HASH",
-       .synopsis = "Implementation of a dialplan associative array",
-       .syntax = "HASH(hashname[,hashkey])",
        .write = hash_write,
        .read = hash_read,
-       .desc =
-               "In two argument mode, gets and sets values to corresponding keys within a named\n"
-               "associative array.  The single-argument mode will only work when assigned to from\n"
-               "a function defined by func_odbc.so.\n",
 };
 
 static struct ast_custom_function hashkeys_function = {
        .name = "HASHKEYS",
-       .synopsis = "Retrieve the keys of a HASH()",
-       .syntax = "HASHKEYS(<hashname>)",
        .read = hashkeys_read,
-       .desc =
-               "Returns a comma-delimited list of the current keys of an associative array\n"
-               "defined by the HASH() function.  Note that if you iterate over the keys of\n"
-               "the result, adding keys during iteration will cause the result of the HASHKEYS\n"
-               "function to change.\n",
 };
 
 static struct ast_custom_function array_function = {
        .name = "ARRAY",
-       .synopsis = "Allows setting multiple variables at once",
-       .syntax = "ARRAY(var1[,var2[...][,varN]])",
        .write = array,
-       .desc =
-               "The comma-separated list passed as a value to which the function is set will\n"
-               "be interpreted as a set of values to which the comma-separated list of\n"
-               "variable names in the argument should be set.\n"
-               "Hence, Set(ARRAY(var1,var2)=1,2) will set var1 to 1 and var2 to 2.\n",
 };
 
 static int acf_sprintf(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
@@ -580,13 +776,7 @@ sprintf_fail:
 
 static struct ast_custom_function sprintf_function = {
        .name = "SPRINTF",
-       .synopsis = "Format a variable according to a format string",
-       .syntax = "SPRINTF(<format>,<arg1>[,...<argN>])",
        .read = acf_sprintf,
-       .desc =
-"Parses the format string specified and returns a string matching that format.\n"
-"Supports most options supported by sprintf(3).  Returns a shortened string if\n"
-"a format specifier is not recognized.\n",
 };
 
 static int quote(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
@@ -613,8 +803,6 @@ static int quote(struct ast_channel *chan, const char *cmd, char *data, char *bu
 
 static struct ast_custom_function quote_function = {
        .name = "QUOTE",
-       .synopsis = "Quotes a given string, escaping embedded quotes as necessary",
-       .syntax = "QUOTE(<string>)",
        .read = quote,
 };
 
@@ -634,8 +822,6 @@ static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf,
 
 static struct ast_custom_function len_function = {
        .name = "LEN",
-       .synopsis = "Returns the length of the argument given",
-       .syntax = "LEN(<string>)",
        .read = len,
 };
 
@@ -670,16 +856,6 @@ static int acf_strftime(struct ast_channel *chan, const char *cmd, char *parse,
 
 static struct ast_custom_function strftime_function = {
        .name = "STRFTIME",
-       .synopsis = "Returns the current date/time in a specified format.",
-       .syntax = "STRFTIME([<epoch>][,[timezone][,format]])",
-       .desc =
-"STRFTIME sports all of the same formats as the underlying C function\n"
-"strftime(3) - see the man page for details.  It also supports the\n"
-"following format:\n"
-" %[n]q - fractions of a second, with leading zeroes.  For example, %3q will\n"
-"         give milliseconds and %1q will give tenths of a second.  The default\n"
-"         is to output milliseconds (n=3).  The common case is to use it in\n"
-"         combination with %S, as in \"%S.%3q\".\n",
        .read = acf_strftime,
 };
 
@@ -722,16 +898,6 @@ static int acf_strptime(struct ast_channel *chan, const char *cmd, char *data,
 
 static struct ast_custom_function strptime_function = {
        .name = "STRPTIME",
-       .synopsis =
-               "Returns the epoch of the arbitrary date/time string structured as described in the format.",
-       .syntax = "STRPTIME(<datetime>,<timezone>,<format>)",
-       .desc =
-               "This is useful for converting a date into an EPOCH time, possibly to pass to\n"
-               "an application like SayUnixTime or to calculate the difference between two\n"
-               "date strings.\n"
-               "\n"
-               "Example:\n"
-               "  ${STRPTIME(2006-03-01 07:30:35,America/Chicago,%Y-%m-%d %H:%M:%S)} returns 1141219835\n",
        .read = acf_strptime,
 };
 
@@ -754,17 +920,6 @@ static int function_eval(struct ast_channel *chan, const char *cmd, char *data,
 
 static struct ast_custom_function eval_function = {
        .name = "EVAL",
-       .synopsis = "Evaluate stored variables.",
-       .syntax = "EVAL(<variable>)",
-       .desc = "Using EVAL basically causes a string to be evaluated twice.\n"
-               "When a variable or expression is in the dialplan, it will be\n"
-               "evaluated at runtime. However, if the result of the evaluation\n"
-               "is in fact a variable or expression, using EVAL will have it\n"
-               "evaluated a second time. For example, if the variable ${MYVAR}\n"
-               "contains \"${OTHERVAR}\", then the result of putting ${EVAL(${MYVAR})}\n"
-               "in the dialplan will be the contents of the variable, OTHERVAR.\n"
-               "Normally, by just putting ${MYVAR} in the dialplan, you would be\n"
-               "left with \"${OTHERVAR}\".\n",
        .read = function_eval,
 };
 
@@ -805,10 +960,7 @@ static int keypadhash(struct ast_channel *chan, const char *cmd, char *data, cha
 
 static struct ast_custom_function keypadhash_function = {
        .name = "KEYPADHASH",
-       .synopsis = "Hash the letters in the string into the equivalent keypad numbers.",
-       .syntax = "KEYPADHASH(<string>)",
        .read = keypadhash,
-       .desc = "Example:  ${KEYPADHASH(Les)} returns \"537\"\n",
 };
 
 static int string_toupper(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
@@ -822,10 +974,7 @@ static int string_toupper(struct ast_channel *chan, const char *cmd, char *data,
 
 static struct ast_custom_function toupper_function = {
        .name = "TOUPPER",
-       .synopsis = "Convert the string to upper case.",
-       .syntax = "TOUPPER(<string>)",
        .read = string_toupper,
-       .desc = "Example: ${TOUPPER(Example)} returns \"EXAMPLE\"\n",
 };
 
 static int string_tolower(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
@@ -839,10 +988,7 @@ static int string_tolower(struct ast_channel *chan, const char *cmd, char *data,
 
 static struct ast_custom_function tolower_function = {
        .name = "TOLOWER",
-       .synopsis = "Convert the string to lower case.",
-       .syntax = "TOLOWER(<string>)",
        .read = string_tolower,
-       .desc = "Example: ${TOLOWER(Example)} returns \"example\"\n",
 };
 
 static int unload_module(void)
@@ -886,7 +1032,7 @@ static int load_module(void)
        res |= ast_custom_function_register(&sprintf_function);
        res |= ast_custom_function_register(&hashkeys_function);
        res |= ast_custom_function_register(&hash_function);
-       res |= ast_register_application(app_clearhash, exec_clearhash, syn_clearhash, desc_clearhash);
+       res |= ast_register_application_xml(app_clearhash, exec_clearhash);
        res |= ast_custom_function_register(&toupper_function);
        res |= ast_custom_function_register(&tolower_function);
 
index 625070217b99d25edc1e89dba8287f6f5ffb1368..a035a05634eb484d72ff56c9431088eaa99cb0d0 100644 (file)
@@ -34,6 +34,42 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/utils.h"
 #include "asterisk/app.h"
 
+/*** DOCUMENTATION
+       <function name="TIMEOUT" language="en_US">
+               <synopsis>
+                       Gets or sets timeouts on the channel. Timeout values are in seconds.
+               </synopsis>
+               <syntax>
+                       <parameter name="timeouttype" required="true">
+                               <para>The timeout that will be manipulated. The possible timeout types
+                               are: <literal>absolute</literal>, <literal>digit</literal> or 
+                               <literal>response</literal></para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>The timeouts that can be manipulated are:</para>
+                       <para><literal>absolute</literal>: The absolute maximum amount of time permitted for a call.
+                       Setting of 0 disables the timeout.</para>
+                       <para><literal>digit</literal>: The maximum amount of time permitted between digits when the
+                       user is typing in an extension.  When this timeout expires,
+                       after the user has started to type in an extension, the
+                       extension will be considered complete, and will be
+                       interpreted.  Note that if an extension typed in is valid,
+                       it will not have to timeout to be tested, so typically at
+                       the expiry of this timeout, the extension will be considered
+                       invalid (and thus control would be passed to the <literal>i</literal>
+                       extension, or if it doesn't exist the call would be
+                       terminated).  The default timeout is 5 seconds.</para>
+                       <para><literal>response</literal>: The maximum amount of time permitted after falling through a
+                       series of priorities for a channel in which the user may
+                       begin typing an extension.  If the user does not type an
+                       extension in this amount of time, control will pass to the
+                       <literal>t</literal> extension if it exists, and if not the call would be
+                       terminated.  The default timeout is 10 seconds.</para>
+               </description>
+       </function>
+ ***/
+
 static int timeout_read(struct ast_channel *chan, const char *cmd, char *data,
                        char *buf, size_t len)
 {
@@ -149,29 +185,6 @@ static int timeout_write(struct ast_channel *chan, const char *cmd, char *data,
 
 static struct ast_custom_function timeout_function = {
        .name = "TIMEOUT",
-       .synopsis = "Gets or sets timeouts on the channel. Timeout values are in seconds.",
-       .syntax = "TIMEOUT(timeouttype)",
-       .desc =
-               "Gets or sets various channel timeouts. The timeouts that can be\n"
-               "manipulated are:\n" "\n"
-               "absolute: The absolute maximum amount of time permitted for a call.  A\n"
-               "          setting of 0 disables the timeout.\n" "\n"
-               "digit:    The maximum amount of time permitted between digits when the\n"
-               "          user is typing in an extension.  When this timeout expires,\n"
-               "          after the user has started to type in an extension, the\n"
-               "          extension will be considered complete, and will be\n"
-               "          interpreted.  Note that if an extension typed in is valid,\n"
-               "          it will not have to timeout to be tested, so typically at\n"
-               "          the expiry of this timeout, the extension will be considered\n"
-               "          invalid (and thus control would be passed to the 'i'\n"
-               "          extension, or if it doesn't exist the call would be\n"
-               "          terminated).  The default timeout is 5 seconds.\n" "\n"
-               "response: The maximum amount of time permitted after falling through a\n"
-               "          series of priorities for a channel in which the user may\n"
-               "          begin typing an extension.  If the user does not type an\n"
-               "          extension in this amount of time, control will pass to the\n"
-               "          't' extension if it exists, and if not the call would be\n"
-               "          terminated.  The default timeout is 10 seconds.\n",
        .read = timeout_read,
        .write = timeout_write,
 };
index 94ae220b6195de264391ad856d9086511ed7d481..5efa6ea3812d643a2f926e48cb8ad086e8e0d53f 100644 (file)
@@ -38,6 +38,35 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/utils.h"
 #include "asterisk/app.h"
 
+/*** DOCUMENTATION
+       <function name="URIENCODE" language="en_US">
+               <synopsis>
+                       Encodes a string to URI-safe encoding according to RFC 2396.
+               </synopsis>
+               <syntax>
+                       <parameter name="data" required="true">
+                               <para>Input string to be encoded.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Returns the encoded string defined in <replaceable>data</replaceable>.</para>
+               </description>
+       </function>
+       <function name="URIDECODE" language="en_US">
+               <synopsis>
+                       Decodes a URI-encoded string according to RFC 2396.
+               </synopsis>
+               <syntax>
+                       <parameter name="data" required="true">
+                               <para>Input string to be decoded.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Returns the decoded URI-encoded <replaceable>data</replaceable> string.</para>
+               </description>
+       </function>
+ ***/
+
 /*! \brief uriencode: Encode URL according to RFC 2396 */
 static int uriencode(struct ast_channel *chan, const char *cmd, char *data,
                     char *buf, size_t len)
@@ -69,15 +98,11 @@ static int uridecode(struct ast_channel *chan, const char *cmd, char *data,
 
 static struct ast_custom_function urldecode_function = {
        .name = "URIDECODE",
-       .synopsis = "Decodes a URI-encoded string according to RFC 2396.",
-       .syntax = "URIDECODE(<data>)",
        .read = uridecode,
 };
 
 static struct ast_custom_function urlencode_function = {
        .name = "URIENCODE",
-       .synopsis = "Encodes a string to URI-safe encoding according to RFC 2396.",
-       .syntax = "URIENCODE(<data>)",
        .read = uriencode,
 };
 
index 973f866c667dd79121564110566895e0d4df9af0..8ed6c218f5a3fc66bd816f5495632c244e579d76 100644 (file)
@@ -34,6 +34,49 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/ast_version.h"
 #include "asterisk/build.h"
 
+/*** DOCUMENTATION
+       <function name="VERSION" language="en_US">
+               <synopsis>
+                       Return the Version info for this Asterisk.
+               </synopsis>
+               <syntax>
+                       <parameter name="info">
+                               <para>The possible values are:</para>
+                               <enumlist>
+                                       <enum name="ASTERISK_VERSION_NUM">
+                                               <para>A string of digits is returned (right now fixed at 999999).</para>
+                                       </enum>
+                                       <enum name="BUILD_USER">
+                                               <para>The string representing the user's name whose account
+                                               was used to configure Asterisk, is returned.</para>
+                                       </enum>
+                                       <enum name="BUILD_HOSTNAME">
+                                               <para>The string representing the name of the host on which Asterisk was configured, is returned.</para>
+                                       </enum>
+                                       <enum name="BUILD_MACHINE">
+                                               <para>The string representing the type of machine on which Asterisk was configured, is returned.</para>
+                                       </enum>
+                                       <enum name="BUILD_OS">
+                                               <para>The string representing the OS of the machine on which Asterisk was configured, is returned.</para>
+                                       </enum>
+                                       <enum name="BUILD_DATE">
+                                               <para>The string representing the date on which Asterisk was configured, is returned.</para>
+                                       </enum>
+                                       <enum name="BUILD_KERNEL">
+                                               <para>The string representing the kernel version of the machine on which Asterisk
+                                               was configured, is returned.</para>
+                                       </enum>
+                               </enumlist>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>If there are no arguments, return the version of Asterisk in this format: SVN-branch-1.4-r44830M</para>
+                       <para>Example:  Set(junky=${VERSION()};</para>
+                       <para>Sets junky to the string <literal>SVN-branch-1.6-r74830M</literal>, or possibly, <literal>SVN-trunk-r45126M</literal>.</para>
+               </description>
+       </function>
+ ***/
+
 static int acf_version_exec(struct ast_channel *chan, const char *cmd,
                         char *parse, char *buffer, size_t buflen)
 {
@@ -70,19 +113,6 @@ static int acf_version_exec(struct ast_channel *chan, const char *cmd,
 
 static struct ast_custom_function acf_version = {
        .name = "VERSION",
-       .synopsis = "Return the Version info for this Asterisk",
-       .syntax = "VERSION([info])",
-       .desc =
-               "If there are no arguments, return the version of Asterisk in this format: SVN-branch-1.4-r44830M\n"
-               "If the argument is 'ASTERISK_VERSION_NUM', a string of digits is returned (right now fixed at 999999).\n"
-               "If the argument is 'BUILD_USER', the string representing the user's name whose account was used to configure Asterisk, is returned.\n"
-               "If the argument is 'BUILD_HOSTNAME', the string representing the name of the host on which Asterisk was configured, is returned.\n"
-               "If the argument is 'BUILD_MACHINE', the string representing the type of machine on which Asterisk was configured, is returned.\n"
-               "If the argument is 'BUILD_OS', the string representing the OS of the machine on which Asterisk was configured, is returned.\n"
-               "If the argument is 'BUILD_DATE', the string representing the date on which Asterisk was configured, is returned.\n"
-               "If the argument is 'BUILD_KERNEL', the string representing the kernel version of the machine on which Asterisk was configured, is returned .\n"
-               "  Example:  Set(junky=${VERSION()}; \n"
-               "  Sets junky to the string 'SVN-branch-1.6-r74830M', or possibly, 'SVN-trunk-r45126M'.\n",
        .read = acf_version_exec,
 };
 
index 24d83140d42538ba231a74feced5ef43195dd0e6..f79669b6d3ea91b76dc1c2e7dc43c83bc5f5fc58 100644 (file)
@@ -39,6 +39,30 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/utils.h"
 #include "asterisk/app.h"
 
+/*** DOCUMENTATION
+       <function name="VMCOUNT" language="en_US">
+               <synopsis>
+                       Count the voicemails in a specified mailbox.
+               </synopsis>
+               <syntax>
+                       <parameter name="vmbox" required="true" argsep="@">
+                               <argument name="vmbox" required="true" />
+                               <argument name="context" required="false">
+                                       <para>If not specified, defaults to <literal>default</literal>.</para>
+                               </argument>
+                       </parameter>
+                       <parameter name="folder" required="false">
+                               <para>If not specified, defaults to <literal>INBOX</literal></para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Count the number of voicemails in a specified mailbox, you could also specify 
+                       the <replaceable>context</replaceable> and the mailbox <replaceable>folder</replaceable>.</para>
+                       <para>Example: <literal>exten => s,1,Set(foo=${VMCOUNT(125)})</literal></para>
+               </description>
+       </function>
+ ***/
+
 static int acf_vmcount_exec(struct ast_channel *chan, const char *cmd, char *argsstr, char *buf, size_t len)
 {
        char *context;
@@ -72,11 +96,6 @@ static int acf_vmcount_exec(struct ast_channel *chan, const char *cmd, char *arg
 
 struct ast_custom_function acf_vmcount = {
        .name = "VMCOUNT",
-       .synopsis = "Counts the voicemail in a specified mailbox",
-       .syntax = "VMCOUNT(vmbox[@context][,folder])",
-       .desc =
-       "  context - defaults to \"default\"\n"
-       "  folder  - defaults to \"INBOX\"\n",
        .read = acf_vmcount_exec,
 };
 
index 530f9b876536b5a0dfba6c2ce313b8b16ef85204..9c8b92b2049b55b856288cfa677d62657c20b45b 100644 (file)
@@ -36,6 +36,26 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/utils.h"
 #include "asterisk/audiohook.h"
 
+/*** DOCUMENTATION
+       <function name="VOLUME" language="en_US">
+               <synopsis>
+                       Set the TX or RX volume of a channel.
+               </synopsis>
+               <syntax>
+                       <parameter name="direction" required="true">
+                               <para>Must be <literal>TX</literal> or <literal>RX</literal>.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>The VOLUME function can be used to increase or decrease the <literal>tx</literal> or
+                       <literal>rx</literal> gain of any channel.</para>
+                       <para>For example:</para>
+                       <para>Set(VOLUME(TX)=3)</para>
+                       <para>Set(VOLUME(RX)=2)</para>
+               </description>
+       </function>
+ ***/
+
 struct volume_information {
        struct ast_audiohook audiohook;
        int tx_gain;
@@ -137,13 +157,6 @@ static int volume_write(struct ast_channel *chan, const char *cmd, char *data, c
 
 static struct ast_custom_function volume_function = {
        .name = "VOLUME",
-       .synopsis = "Set the TX or RX volume of a channel",
-       .syntax = "VOLUME(TX|RX)",
-       .desc =
-       "  The VOLUME function can be used to increase or decrease the tx or\n"
-       "rx gain of any channel.  For example:\n"
-       "  Set(VOLUME(TX)=3)\n"
-       "  Set(VOLUME(RX)=2)\n",
        .write = volume_write,
 };
 
index fe9aa2c04104bdf9ad4a10f70c820640e99c030b..be4542d7a8d5cb78fab36164fc58516bd8e70b77 100644 (file)
@@ -56,4 +56,10 @@ int ast_timing_init(void);           /*!< Provided by timing.c */
  */
 int ast_module_reload(const char *name);
 
+/*! \brief Load XML documentation. Provided by pbx.c 
+ *  \retval 1 on error.
+ *  \retval 0 on success. 
+ */
+int ast_load_documentation(void);
+
 #endif /* _ASTERISK__PRIVATE_H */
index 3417c738ee33298f32b73db500ee7c9bb31ae46d..79134bd3c1ac9b8dd5670afc8966d287e847376d 100644 (file)
 /* Define to 1 if you have the <libintl.h> header file. */
 #undef HAVE_LIBINTL_H
 
+/* Define if your system has the LIBXML2 libraries. */
+#undef HAVE_LIBXML2
+
 /* Define to 1 if you have the <limits.h> header file. */
 #undef HAVE_LIMITS_H
 
index e481fbec4bb44d42933b49433e79e331c5741038..0b431f5e020b7eae1dd615939e449ad807cbbbcd 100644 (file)
@@ -182,4 +182,15 @@ typedef unsigned int       uint;
 typedef unsigned long long uint64_t;
 #endif
 
+/* glob compat stuff */ 
+#if defined(__Darwin__) || defined(__CYGWIN__)
+#define GLOB_ABORTED GLOB_ABEND
+#endif
+#include <glob.h>
+#ifdef SOLARIS
+#define MY_GLOB_FLAGS   GLOB_NOCHECK
+#else
+#define MY_GLOB_FLAGS   (GLOB_NOMAGIC|GLOB_BRACE)
+#endif
+
 #endif
index 086271ce5a75b9eb1fe5ad69a141466c447b5b8a..7527c579f1babbd5da3f746173a075d4e4d72171 100644 (file)
@@ -76,8 +76,14 @@ struct ast_config {
 /*! \brief A registered application */
 struct ast_app {
        int (*execute)(struct ast_channel *chan, void *data);
-       const char *synopsis;                   /*!< Synopsis text for 'show applications' */
-       const char *description;                /*!< Description (help text) for 'show application &lt;name&gt;' */
+       AST_DECLARE_STRING_FIELDS(
+               AST_STRING_FIELD(synopsis);     /*!< Synopsis text for 'show applications' */
+               AST_STRING_FIELD(description);  /*!< Description (help text) for 'show application &lt;name&gt;' */
+               AST_STRING_FIELD(syntax);       /*!< Syntax text for 'core show applications' */
+               AST_STRING_FIELD(arguments);    /*!< Arguments description */
+               AST_STRING_FIELD(seealso);      /*!< See also */
+       );
+       enum ast_xmldoc_src docsrc;             /*!< Where the documentation come from. */
        AST_RWLIST_ENTRY(ast_app) list;         /*!< Next app in list */
        void *module;                   /*!< Module this app belongs to */
        char name[0];                           /*!< Name of the application */
index f466395c027ba48881e605d1f7bfd8b7d374fd1c..640c5af32f5b6778658f0fa0e968b8688e33747a 100644 (file)
@@ -380,6 +380,23 @@ static void __restore_globals(void)
  */
 #define ast_register_application(app, execute, synopsis, description) ast_register_application2(app, execute, synopsis, description, ast_module_info->self)
 
+/*! 
+ * \brief Register an application using XML documentation.
+ *
+ * \param app Short name of the application
+ * \param execute a function callback to execute the application. It should return
+ *                non-zero if the channel needs to be hung up.
+ * 
+ * This registers an application with Asterisk's internal application list. 
+ * \note The individual applications themselves are responsible for registering and unregistering
+ *       and unregistering their own CLI commands.
+ * 
+ * \retval 0 success 
+ * \retval -1 failure.
+ */
+#define ast_register_application_xml(app, execute) ast_register_application(app, execute, NULL, NULL)
+
+
 /*!
  * \brief Register an application.
  *
index d2d95accae57995b5ab71e4b01f3085ae9f91fdf..3348bb8d75bdcb1f58fdc146a6328546194b1e6c 100644 (file)
@@ -26,6 +26,7 @@
 #include "asterisk/sched.h"
 #include "asterisk/chanvars.h"
 #include "asterisk/hashtab.h"
+#include "asterisk/stringfields.h"
 
 #if defined(__cplusplus) || defined(c_plusplus)
 extern "C" {
@@ -73,12 +74,23 @@ struct ast_sw;
 /*! \brief Typedef for devicestate and hint callbacks */
 typedef int (*ast_state_cb_type)(char *context, char* id, enum ast_extension_states state, void *data);
 
+/*! \brief From where the documentation come from */
+enum ast_doc_src {
+       AST_XML_DOC,            /*!< From XML documentation */
+       AST_STATIC_DOC          /*!< From application/function registration */
+};
+
 /*! \brief Data structure associated with a custom dialplan function */
 struct ast_custom_function {
-       const char *name;               /*!< Name */
-       const char *synopsis;           /*!< Short description for "show functions" */
-       const char *desc;               /*!< Help text that explains it all */
-       const char *syntax;             /*!< Syntax description */
+       const char *name;                       /*!< Name */
+       AST_DECLARE_STRING_FIELDS(
+               AST_STRING_FIELD(synopsis);     /*!< Synopsis text for 'show functions' */
+               AST_STRING_FIELD(desc);         /*!< Description (help text) for 'show functions &lt;name&gt;' */
+               AST_STRING_FIELD(syntax);       /*!< Syntax text for 'core show functions' */
+               AST_STRING_FIELD(arguments);    /*!< Arguments description */
+               AST_STRING_FIELD(seealso);      /*!< See also */
+       );
+       enum ast_doc_src docsrc;                /*!< Where the documentation come from */
        int (*read)(struct ast_channel *, const char *, char *, char *, size_t);        /*!< Read function, if read is supported */
        int (*write)(struct ast_channel *, const char *, char *, const char *);         /*!< Write function, if write is supported */
        struct ast_module *mod;         /*!< Module this custom function belongs to */
index 19315b02f20bc01f3341a4077de931e67157f3bc..16a60c38af73e21bc3dbb34fff024345b079d849 100644 (file)
@@ -387,6 +387,21 @@ void ast_str_reset(struct ast_str *buf),
 }
 )
 
+/*! \brief Trims trailing whitespace characters from an ast_str string.
+ *  \param buf A pointer to the ast_str string.
+ */
+AST_INLINE_API(
+void ast_str_trim_blanks(struct ast_str *buf),
+{
+       if (!buf) {
+               return;
+       }
+       while (buf->used && buf->str[buf->used - 1] < 33) {
+               buf->str[--(buf->used)] = '\0';
+       }
+}
+)
+
 /*
  * AST_INLINE_API() is a macro that takes a block of code as an argument.
  * Using preprocessor #directives in the argument is not supported by all
index 3277f00429050283381b05301a54be3461e026d3..8c6cab43e922c4aec39f39008c65866a9d7b7a58 100644 (file)
@@ -64,6 +64,28 @@ extern "C" {
 
 char *term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout);
 
+/*!
+ * \brief Append a color sequence to an ast_str
+ *
+ * \param str The string to append to
+ * \param fgcolor foreground color
+ * \param bgcolor background color
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ */
+int ast_term_color_code(struct ast_str **str, int fgcolor, int bgcolor);
+
+/*!
+ * \brief Write a color sequence to a string
+ *
+ * \param outbuf the location to write to
+ * \param fgcolor foreground color
+ * \param bgcolor background color
+ * \param maxout maximum number of characters to write
+ *
+ * \return outbuf
+ */
 char *term_color_code(char *outbuf, int fgcolor, int bgcolor, int maxout);
 
 char *term_strip(char *outbuf, char *inbuf, int maxout);
diff --git a/include/asterisk/xml.h b/include/asterisk/xml.h
new file mode 100644 (file)
index 0000000..8ed9ffd
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2008, Eliel C. Sardanons (LU1ALY) <eliels@gmail.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+#ifndef _ASTERISK_XML_H
+#define _ASTERISK_XML_H
+
+/*! \file 
+ *  \brief Asterisk XML abstraction layer
+ */
+
+struct ast_xml_node;
+struct ast_xml_doc;
+
+/*! \brief Initialize the XML library implementation. 
+ *         This function is used to setup everything needed
+ *         to start working with the xml implementation.
+ *  \retval 0 On success.
+ *  \retval 1 On error.
+ */
+int ast_xml_init(void);
+
+/*! \brief Cleanup library allocated global data. 
+ *  \retval 0 On success.
+ *  \retval 1 On error.
+ */
+int ast_xml_finish(void);
+
+/*! \brief Open an XML document.
+ *  \param filename Document path.
+ *  \retval NULL on error.
+ *  \retval The ast_xml_doc reference to the open document.
+ */
+struct ast_xml_doc *ast_xml_open(char *filename);
+
+/*! \brief Close an already open document and free the used
+ *        structure.
+ *  \retval doc The document reference.
+ */
+void ast_xml_close(struct ast_xml_doc *doc);
+
+/*! \brief Get the document root node.
+ *  \param doc Document reference
+ *  \retval NULL on error
+ *  \retval The root node on success.
+ */
+struct ast_xml_node *ast_xml_get_root(struct ast_xml_doc *doc);
+
+/*! \brief Free node 
+ *  \param node Node to be released.
+ */
+void ast_xml_free_node(struct ast_xml_node *node);
+
+/*! \brief Free an attribute returned by ast_xml_get_attribute()
+ *  \param data pointer to be freed.
+ */
+void ast_xml_free_attr(const char *attribute);
+
+/*! \brief Free a content element that was returned by ast_xml_get_text()
+ *  \param text text to be freed.
+ */
+void ast_xml_free_text(const char *text);
+
+/*! \brief Get a node attribute by name
+ *  \param node Node where to search the attribute.
+ *  \param attrname Attribute name.
+ *  \retval NULL on error
+ *  \retval The attribute value on success.
+ */
+const char *ast_xml_get_attribute(struct ast_xml_node *node, const char *attrname);
+
+/*! \brief Find a node element by name.
+ *  \param node This is the node starting point.
+ *  \param name Node name to find.
+ *  \param attrname attribute name to match (if NULL it won't be matched).
+ *  \param attrvalue attribute value to match (if NULL it won't be matched).
+ *  \retval NULL if not found
+ *  \retval The node on success.
+ */
+struct ast_xml_node *ast_xml_find_element(struct ast_xml_node *root_node, const char *name, const char *attrname, const char *attrvalue);
+
+/*! \brief Get an element content string.
+ *  \param node Node from where to get the string.
+ *  \retval NULL on error.
+ *  \retval The text content of node.
+ */
+const char *ast_xml_get_text(struct ast_xml_node *node);
+
+/*! \brief Get the name of a node. */
+const char *ast_xml_node_get_name(struct ast_xml_node *node);
+
+/*! \brief Get the node's children. */
+struct ast_xml_node *ast_xml_node_get_children(struct ast_xml_node *node);
+
+/*! \brief Get the next node in the same level. */
+struct ast_xml_node *ast_xml_node_get_next(struct ast_xml_node *node);
+
+/*! \brief Get the previous node in the same leve. */
+struct ast_xml_node *ast_xml_node_get_prev(struct ast_xml_node *node);
+
+/*! \brief Get the parent of a specified node. */
+struct ast_xml_node *ast_xml_node_get_parent(struct ast_xml_node *node);
+
+/* Features using ast_xml_ */
+#ifdef HAVE_LIBXML2
+#define AST_XML_DOCS
+#endif
+
+#endif /* _ASTERISK_XML_H */
+
index b1ef7ef77e0ae7e7f45dba77d3653355804ccd0d..cab6f9b9a89c7a534f57be60d8138771aa2d0479 100644 (file)
@@ -28,7 +28,7 @@ OBJS= tcptls.o io.o sched.o logger.o frame.o loader.o config.o channel.o \
        cryptostub.o sha1.o http.o fixedjitterbuf.o abstract_jb.o \
        strcompat.o threadstorage.o dial.o event.o adsistub.o audiohook.o \
        astobj2.o hashtab.o global_datastores.o version.o \
-       features.o taskprocessor.o timing.o datastore.o
+       features.o taskprocessor.o timing.o datastore.o xml.o
 
 # we need to link in the objects statically, not as a library, because
 # otherwise modules will not have them available if none of the static
@@ -41,7 +41,7 @@ OBJS+=say.o
 
 AST_LIBS += $(SSL_LIB)
 AST_LIBS += $(BKTR_LIB)
-
+AST_LIBS += $(LIBXML2_LIB) 
 
 ifeq ($(POLL_AVAILABLE),)
   OBJS+=poll.o
index 73e27c229618b97ee822772639b805ab67e126bc..239acd7ffd07e45fa6fef16744c94408c9ad2923 100644 (file)
@@ -117,6 +117,7 @@ int daemon(int, int);  /* defined in libresolv of all places */
 #include "asterisk/devicestate.h"
 #include "asterisk/module.h"
 #include "asterisk/dsp.h"
+#include "asterisk/xml.h"
 #include "asterisk/buildinfo.h"
 
 #include "asterisk/doxyref.h"          /* Doxygen documentation */
@@ -3322,6 +3323,11 @@ int main(int argc, char *argv[])
                exit(1);
        }
 
+#ifdef AST_XML_DOCS
+       /* Load XML documentation. */
+       ast_load_documentation();
+#endif
+
        if (load_modules(1)) {          /* Load modules, pre-load only */
                printf("%s", term_quit());
                exit(1);
index a382a7a809481fa4ed1dc6d4d7e91e9866dad53d..b3abe27301220145907bd1a4ab81da543433d728 100644 (file)
@@ -39,24 +39,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
 #define AST_INCLUDE_GLOB 1
 
-#ifdef AST_INCLUDE_GLOB
-/* glob compat stuff - eventually this should go in compat.h or some
- * header in include/asterisk/
- */
-#if defined(__Darwin__) || defined(__CYGWIN__)
-#define GLOB_ABORTED GLOB_ABEND
-#endif
-
-#include <glob.h>
-
-#ifdef SOLARIS
-#define MY_GLOB_FLAGS  GLOB_NOCHECK
-#else
-#define MY_GLOB_FLAGS  (GLOB_NOMAGIC|GLOB_BRACE)
-#endif
-
-#endif
-
 #include "asterisk/config.h"
 #include "asterisk/cli.h"
 #include "asterisk/lock.h"
index 82b85669cd36453d989b97fe531f62af0a604735..adf5086aac2870cdb09d1e3819b6b44c47a8b7ce 100644 (file)
@@ -56,6 +56,98 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/global_datastores.h"
 #include "asterisk/astobj2.h"
 
+/*** DOCUMENTATION
+       <application name="Bridge" language="en_US">
+               <synopsis>
+                       Bridge two channels.
+               </synopsis>
+               <syntax>
+                       <parameter name="channel" required="true">
+                               <para>The current channel is bridged to the specified <replaceable>channel</replaceable>.</para>
+                       </parameter>
+                       <parameter name="options">
+                               <optionlist>
+                                       <option name="p">
+                                               <para>Play a courtesy tone to <replaceable>channel</replaceable>.</para>
+                                       </option>
+                               </optionlist>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Allows the ability to bridge two channels via the dialplan.</para>
+                       <para>This application sets the following channel variable upon completion:</para>
+                       <variablelist>
+                               <variable name="BRIDGERESULT">
+                                       <para>The result of the bridge attempt as a text string.</para>
+                                       <value name="SUCCESS" />
+                                       <value name="FAILURE" />
+                                       <value name="LOOP" />
+                                       <value name="NONEXISTENT" />
+                                       <value name="INCOMPATIBLE" />
+                               </variable>
+                       </variablelist>
+               </description>
+       </application>
+       <application name="ParkedCall" language="en_US">
+               <synopsis>
+                       Answer a parked call.
+               </synopsis>
+               <syntax>
+                       <parameter name="exten" required="true" />
+               </syntax>
+               <description>
+                       <para>Used to connect to a parked call. This application is always
+                       registered internally and does not need to be explicitly added
+                       into the dialplan, although you should include the <literal>parkedcalls</literal>
+                       context. If no extension is provided, then the first available
+                       parked call will be acquired.</para>
+               </description>
+       </application>
+       <application name="Park" language="en_US">
+               <synopsis>
+                       Park yourself.
+               </synopsis>
+               <syntax>
+                       <parameter name="timeout">
+                               <para>A custom parking timeout for this parked call.</para>
+                       </parameter>
+                       <parameter name="return_context">
+                               <para>The context to return the call to after it times out.</para>
+                       </parameter>
+                       <parameter name="return_exten">
+                               <para>The extension to return the call to after it times out.</para>
+                       </parameter>
+                       <parameter name="return_priority">
+                               <para>The priority to return the call to after it times out.</para>
+                       </parameter>
+                       <parameter name="options">
+                               <para>A list of options for this parked call.</para>
+                               <optionlist>
+                                       <option name="r">
+                                               <para>Send ringing instead of MOH to the parked call.</para>
+                                       </option>
+                                       <option name="R">
+                                               <para>Randomize the selection of a parking space.</para>
+                                       </option>
+                                       <option name="s">
+                                               <para>Silence announcement of the parking space number.</para>
+                                       </option>
+                               </optionlist>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Used to park yourself (typically in combination with a supervised
+                       transfer to know the parking space). This application is always
+                       registered internally and does not need to be explicitly added
+                       into the dialplan, although you should include the <literal>parkedcalls</literal>
+                       context (or the context specified in <filename>features.conf</filename>).</para>
+                       <para>If you set the <variable>PARKINGEXTEN</variable> variable to an extension in your
+                       parking context, Park() will park the call on that extension, unless
+                       it already exists. In that case, execution will continue at next priority.</para>
+               </description>
+       </application>
+ ***/
+
 #define DEFAULT_PARK_TIME 45000
 #define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000
 #define DEFAULT_FEATURE_DIGIT_TIMEOUT 2000
@@ -150,41 +242,8 @@ static unsigned int atxfercallbackretries;
 static char *registrar = "features";              /*!< Registrar for operations */
 
 /* module and CLI command definitions */
-static char *synopsis = "Answer a parked call";
-
-static char *descrip = "ParkedCall(exten): "
-"Used to connect to a parked call.  This application is always\n"
-"registered internally and does not need to be explicitly added\n"
-"into the dialplan, although you should include the 'parkedcalls'\n"
-"context.  If no extension is provided, then the first available\n"
-"parked call will be acquired.\n";
-
 static char *parkcall = PARK_APP_NAME;
 
-static char *synopsis2 = "Park yourself";
-
-static char *descrip2 = 
-"   Park([timeout,[return_context,[return_exten,[return_priority,[options]]]]]):"
-"Used to park yourself (typically in combination with a supervised\n"
-"transfer to know the parking space). This application is always\n"
-"registered internally and does not need to be explicitly added\n"
-"into the dialplan, although you should include the 'parkedcalls'\n"
-"context (or the context specified in features.conf).\n\n"
-"If you set the PARKINGEXTEN variable to an extension in your\n"
-"parking context, Park() will park the call on that extension, unless\n"
-"it already exists. In that case, execution will continue at next\n"
-"priority.\n"
-"   This application can accept arguments as well.\n"
-" timeout - A custom parking timeout for this parked call.\n"
-" return_context - The context to return the call to after it times out.\n"
-" return_exten - The extension to return the call to after it times out.\n"
-" return_priority - The priority to return the call to after it times out.\n"
-" options - A list of options for this parked call.  Valid options are:\n"
-"    'r' - Send ringing instead of MOH to the parked call.\n"
-"    'R' - Randomize the selection of a parking space.\n"
-"    's' - Silence announcement of the parking space number.\n"
-"";
-
 static struct ast_app *monitor_app = NULL;
 static int monitor_ok = 1;
 
@@ -3962,16 +4021,6 @@ int ast_pickup_call(struct ast_channel *chan)
 }
 
 static char *app_bridge = "Bridge";
-static char *bridge_synopsis = "Bridge two channels";
-static char *bridge_descrip =
-"Usage: Bridge(channel[,options])\n"
-"      Allows the ability to bridge two channels via the dialplan.\n"
-"The current channel is bridged to the specified 'channel'.\n"
-"  Options:\n"
-"    p - Play a courtesy tone to 'channel'.\n"
-"This application sets the following channel variable upon completion:\n"
-" BRIDGERESULT    The result of the bridge attempt as a text string, one of\n"
-"           SUCCESS | FAILURE | LOOP | NONEXISTENT | INCOMPATIBLE\n";
 
 enum {
        BRIDGE_OPT_PLAYTONE = (1 << 0),
@@ -4113,7 +4162,7 @@ int ast_features_init(void)
 {
        int res;
 
-       ast_register_application2(app_bridge, bridge_exec, bridge_synopsis, bridge_descrip, NULL);
+       ast_register_application2(app_bridge, bridge_exec, NULL, NULL, NULL);
 
        parkinglots = ao2_container_alloc(7, parkinglot_hash_cb, parkinglot_cmp_cb);
 
@@ -4121,9 +4170,9 @@ int ast_features_init(void)
                return res;
        ast_cli_register_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry));
        ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
-       res = ast_register_application2(parkedcall, park_exec, synopsis, descrip, NULL);
+       res = ast_register_application2(parkedcall, park_exec, NULL, NULL, NULL);
        if (!res)
-               res = ast_register_application2(parkcall, park_call_exec, synopsis2, descrip2, NULL);
+               res = ast_register_application2(parkcall, park_call_exec, NULL, NULL, NULL);
        if (!res) {
                ast_manager_register("ParkedCalls", 0, manager_parking_status, "List parked calls");
                ast_manager_register2("Park", EVENT_FLAG_CALL, manager_park, "Park a channel", mandescr_park); 
index b86cb38cef09f64999bd81cee8ca3af0f4468cad..0df8b13776196f8109145c46833fb449259e01eb 100644 (file)
@@ -12,7 +12,7 @@
  * channels for your use.
  *
  * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
+* the GNU General Public License Version 2. See the LICENSE file
  * at the top of the source tree.
  */
 
@@ -59,12 +59,12 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/musiconhold.h"
 #include "asterisk/app.h"
 #include "asterisk/devicestate.h"
-#include "asterisk/stringfields.h"
 #include "asterisk/event.h"
 #include "asterisk/hashtab.h"
 #include "asterisk/module.h"
 #include "asterisk/indications.h"
 #include "asterisk/taskprocessor.h"
+#include "asterisk/xml.h"
 
 /*!
  * \note I M P O R T A N T :
@@ -87,6 +87,541 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  *
  */
 
+/*** DOCUMENTATION
+       <application name="Answer" language="en_US">
+               <synopsis>
+                       Answer a channel if ringing.
+               </synopsis>
+               <syntax>
+                       <parameter name="delay">
+                               <para>Asterisk will wait this number of milliseconds before returning to
+                               the dialplan after answering the call.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>If the call has not been answered, this application will
+                       answer it. Otherwise, it has no effect on the call.</para>
+               </description>
+       </application>
+       <application name="BackGround" language="en_US">
+               <synopsis>
+                       Play an audio file while waiting for digits of an extension to go to.
+               </synopsis>
+               <syntax>
+                       <parameter name="filenames" required="true" argsep="&amp;">
+                               <argument name="filename1" required="true" />
+                               <argument name="filename2" multiple="true" />
+                       </parameter>
+                       <parameter name="options">
+                               <optionlist>
+                                       <option name="s">
+                                               <para>Causes the playback of the message to be skipped
+                                               if the channel is not in the <literal>up</literal> state (i.e. it
+                                               hasn't been answered yet). If this happens, the
+                                               application will return immediately.</para>
+                                       </option>
+                                       <option name="n">
+                                               <para>Don't answer the channel before playing the files.</para>
+                                       </option>
+                                       <option name="m">
+                                               <para>Only break if a digit hit matches a one digit
+                                               extension in the destination context.</para>
+                                       </option>
+                               </optionlist>
+                       </parameter>
+                       <parameter name="langoverride">
+                               <para>Explicitly specifies which language to attempt to use for the requested sound files.</para>
+                       </parameter>
+                       <parameter name="context">
+                               <para>This is the dialplan context that this application will use when exiting
+                               to a dialed extension.</para>
+                       </parameter>    
+               </syntax>
+               <description>
+                       <para>This application will play the given list of files <emphasis>(do not put extension)</emphasis>
+                       while waiting for an extension to be dialed by the calling channel. To continue waiting
+                       for digits after this application has finished playing files, the <literal>WaitExten</literal>
+                       application should be used.</para>
+                       <para>If one of the requested sound files does not exist, call processing will be terminated.</para>
+                       <para>This application sets the following channel variable upon completion:</para>
+                       <variablelist>
+                               <variable name="BACKGROUNDSTATUS">
+                                       <para>The status of the background attempt as a text string.</para>
+                                       <value name="SUCCESS" />
+                                       <value name="FAILED" />
+                               </variable>
+                       </variablelist>
+               </description>
+               <see-also>
+                       <ref type="application">Playback</ref>
+               </see-also>
+       </application>
+       <application name="Busy" language="en_US">
+               <synopsis>
+                       Indicate the Busy condition.
+               </synopsis>
+               <syntax>
+                       <parameter name="timeout">
+                               <para>If specified, the calling channel will be hung up after the specified number of seconds.
+                               Otherwise, this application will wait until the calling channel hangs up.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>This application will indicate the busy condition to the calling channel.</para>
+               </description>
+       </application>
+       <application name="Congestion" language="en_US">
+               <synopsis>
+                       Indicate the Congestion condition.
+               </synopsis>
+               <syntax>
+                       <parameter name="timeout">
+                               <para>If specified, the calling channel will be hung up after the specified number of seconds.
+                               Otherwise, this application will wait until the calling channel hangs up.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>This application will indicate the congestion condition to the calling channel.</para>
+               </description>
+       </application>
+       <application name="ExecIfTime" language="en_US">
+               <synopsis>
+                       Conditional application execution based on the current time.
+               </synopsis>
+               <syntax argsep="?">
+                       <parameter name="day_condition" required="true">
+                               <argument name="times" required="true" />
+                               <argument name="weekdays" required="true" />
+                               <argument name="mdays" required="true" />
+                               <argument name="months" required="true" />
+                       </parameter>
+                       <parameter name="appname" required="true" hasparams="optional">
+                               <argument name="appargs" required="true" />
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>This application will execute the specified dialplan application, with optional
+                       arguments, if the current time matches the given time specification.</para>
+               </description>
+       </application>
+       <application name="Goto" language="en_US">
+               <synopsis>
+                       Jump to a particular priority, extension, or context.
+               </synopsis>
+               <syntax>
+                       <parameter name="context" />
+                       <parameter name="extensions" />
+                       <parameter name="priority" required="true" />
+               </syntax>
+               <description>
+                       <para>This application will set the current context, extension, and priority in the channel structure.
+                       After it completes, the pbx engine will continue dialplan execution at the specified location.
+                       If no specific <replaceable>extension</replaceable>, or <replaceable>extension</replaceable> and
+                       <replaceable>context</replaceable>, are specified, then this application will
+                       just set the specified <replaceable>priority</replaceable> of the current extension.</para>
+                       <para>At least a <replaceable>priority</replaceable> is required as an argument, or the goto will
+                       return a <literal>-1</literal>, and the channel and call will be terminated.</para>
+                       <para>If the location that is put into the channel information is bogus, and asterisk cannot
+                       find that location in the dialplan, then the execution engine will try to find and execute the code in
+                       the <literal>i</literal> (invalid) extension in the current context. If that does not exist, it will try to execute the
+                       <literal>h</literal> extension. If either or neither the <literal>h</literal> or <literal>i</literal> extensions
+                       have been defined, the channel is hung up, and the execution of instructions on the channel is terminated.
+                       What this means is that, for example, you specify a context that does not exist, then
+                       it will not be possible to find the <literal>h</literal> or <literal>i</literal> extensions,
+                       and the call will terminate!</para>
+               </description>
+       </application>
+       <application name="GotoIf" language="en_US">
+               <synopsis>
+                       Conditional goto.
+               </synopsis>
+               <syntax argsep="?">
+                       <parameter name="condition" required="true" />
+                       <parameter name="destination" required="true" argsep=":">
+                               <argument name="labeliftrue">
+                                       <para>Continue at <replaceable>labeliftrue</replaceable> if the condition is true.</para>
+                               </argument>
+                               <argument name="labeliffalse">
+                                       <para>Continue at <replaceable>labeliffalse</replaceable> if the condition is false.</para>
+                               </argument>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>This application will set the current context, extension, and priority in the channel structure
+                       based on the evaluation of the given condition. After this application completes, the
+                       pbx engine will continue dialplan execution at the specified location in the dialplan.
+                       The labels are specified with the same syntax as used within the Goto application.
+                       If the label chosen by the condition is omitted, no jump is performed, and the execution passes to the
+                       next instruction. If the target location is bogus, and does not exist, the execution engine will try
+                       to find and execute the code in the <literal>i</literal> (invalid) extension in the current context.
+                       If that does not exist, it will try to execute the <literal>h</literal> extension.
+                       If either or neither the <literal>h</literal> or <literal>i</literal> extensions have been defined,
+                       the channel is hung up, and the execution of instructions on the channel is terminated.
+                       Remember that this command can set the current context, and if the context specified
+                       does not exist, then it will not be able to find any 'h' or 'i' extensions there, and
+                       the channel and call will both be terminated!.</para>
+               </description>
+       </application>
+       <application name="GotoIfTime" language="en_US">
+               <synopsis>
+                       Conditional Goto based on the current time.
+               </synopsis>
+               <syntax argsep="?">
+                       <parameter name="condition" required="true">
+                               <argument name="times" required="true" />
+                               <argument name="weekdays" required="true" />
+                               <argument name="mdays" required="true" />
+                               <argument name="months" required="true" />
+                       </parameter>
+                       <parameter name="destination" required="true" argsep=":">
+                               <argument name="labeliftrue" />
+                               <argument name="labeliffalse" />
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>This application will set the context, extension, and priority in the channel structure
+                       based on the evaluation of the given time specification. After this application completes,
+                       the pbx engine will continue dialplan execution at the specified location in the dialplan.
+                       If the current time is within the given time specification, the channel will continue at
+                       <replaceable>labeliftrue</replaceable>. Otherwise the channel will continue at <replaceable>labeliffalse</replaceable>.
+                       If the label chosen by the condition is omitted, no jump is performed, and execution passes to the next
+                       instruction. If the target jump location is bogus, the same actions would be taken as for <literal>Goto</literal>.
+                       Further information on the time specification can be found in examples
+                       illustrating how to do time-based context includes in the dialplan.</para>
+               </description>
+       </application>
+       <application name="ImportVar" language="en_US">
+               <synopsis>
+                       Import a variable from a channel into a new variable.
+               </synopsis>
+               <syntax argsep="=">
+                       <parameter name="newvar" required="true" />
+                       <parameter name="vardata" required="true">
+                               <argument name="channelname" required="true" />
+                               <argument name="variable" required="true" />
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>This application imports a <replaceable>variable</replaceable> from the specified
+                       <replaceable>channel</replaceable> (as opposed to the current one) and stores it as a variable
+                       (<replaceable>newvar</replaceable>) in the current channel (the channel that is calling this
+                       application). Variables created by this application have the same inheritance properties as those
+                       created with the <literal>Set</literal> application.</para>
+               </description>
+               <see-also>
+                       <ref type="application">Set</ref>
+               </see-also>
+       </application>
+       <application name="Hangup" language="en_US">
+               <synopsis>
+                       Hang up the calling channel.
+               </synopsis>
+               <syntax>
+                       <parameter name="causecode">
+                               <para>If a <replaceable>causecode</replaceable> is given the channel's
+                               hangup cause will be set to the given value.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>This application will hang up the calling channel.</para>
+               </description>
+       </application>
+       <application name="Incomplete" language="en_US">
+               <synopsis>
+                       Returns AST_PBX_INCOMPLETE value.
+               </synopsis>
+               <syntax>
+                       <parameter name="n">
+                               <para>If specified, then Incomplete will not attempt to answer the channel first.</para>
+                               <note><para>Most channel types need to be in Answer state in order to receive DTMF.</para></note>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Signals the PBX routines that the previous matched extension is incomplete
+                       and that further input should be allowed before matching can be considered
+                       to be complete.  Can be used within a pattern match when certain criteria warrants
+                       a longer match.</para>
+                       
+               </description>
+       </application>
+       <application name="KeepAlive" language="en_US">
+               <synopsis>
+                       Returns AST_PBX_KEEPALIVE value.
+               </synopsis>
+               <syntax />
+               <description>
+                       <para>This application is chiefly meant for internal use with Gosubs. Please do not run
+                       it alone from the dialplan!</para>
+               </description>
+       </application>
+       <application name="NoOp" language="en_US">
+               <synopsis>
+                       Do Nothing (No Operation).
+               </synopsis>
+               <syntax>
+                       <parameter name="text">
+                               <para>Any text provided can be viewed at the Asterisk CLI.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>This application does nothing. However, it is useful for debugging purposes.</para>
+                       <para>This method can be used to see the evaluations of variables or functions without having any effect.</para>
+               </description>
+               <see-also>
+                       <ref type="application">Verbose</ref>
+               </see-also>
+       </application>
+       <application name="Proceeding" language="en_US">
+               <synopsis>
+                       Indicate proceeding.
+               </synopsis>
+               <syntax />
+               <description>
+                       <para>This application will request that a proceeding message be provided to the calling channel.</para>
+               </description>
+       </application>
+       <application name="Progress" language="en_US">
+               <synopsis>
+                       Indicate progress.
+               </synopsis>
+               <syntax />
+               <description>
+                       <para>This application will request that in-band progress information be provided to the calling channel.</para>
+               </description>
+       </application>
+       <application name="RaiseException" language="en_US">
+               <synopsis>
+                       Handle an exceptional condition.
+               </synopsis>
+               <syntax>
+                       <parameter name="reason" required="true" />
+               </syntax>
+               <description>
+                       <para>This application will jump to the <literal>e</literal> extension in the current context, setting the
+                       dialplan function EXCEPTION(). If the <literal>e</literal> extension does not exist, the call will hangup.</para>
+               </description>
+       </application>
+       <application name="ResetCDR" language="en_US">
+               <synopsis>
+                       Resets the Call Data Record.
+               </synopsis>
+               <syntax>
+                       <parameter name="options">
+                               <optionlist>
+                                       <option name="w">
+                                               <para>Store the current CDR record before resetting it.</para>
+                                       </option>
+                                       <option name="a">
+                                               <para>Store any stacked records.</para>
+                                       </option>
+                                       <option name="v">
+                                               <para>Save CDR variables.</para>
+                                       </option>
+                                       <option name="e">
+                                               <para>Enable CDR only (negate effects of NoCDR).</para>
+                                       </option>
+                               </optionlist>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>This application causes the Call Data Record to be reset.</para>
+               </description>
+       </application>
+       <application name="Ringing" language="en_US">
+               <synopsis>
+                       Indicate ringing tone.
+               </synopsis>
+               <syntax />
+               <description>
+                       <para>This application will request that the channel indicate a ringing tone to the user.</para>
+               </description>
+       </application>
+       <application name="SayAlpha" language="en_US">
+               <synopsis>
+                       Say Alpha.
+               </synopsis>
+               <syntax>
+                       <parameter name="string" required="true" />
+               </syntax>
+               <description>
+                       <para>This application will play the sounds that correspond to the letters of the
+                       given <replaceable>string</replaceable>.</para>
+               </description>
+       </application>
+       <application name="SayDigits" language="en_US">
+               <synopsis>
+                       Say Digits.
+               </synopsis>
+               <syntax>
+                       <parameter name="digits" required="true" />
+               </syntax>
+               <description>
+                       <para>This application will play the sounds that correspond to the digits of
+                       the given number. This will use the language that is currently set for the channel.</para>
+               </description>
+       </application>
+       <application name="SayNumber" language="en_US">
+               <synopsis>
+                       Say Number.
+               </synopsis>
+               <syntax>
+                       <parameter name="digits" required="true" />
+                       <parameter name="gender" />
+               </syntax>
+               <description>
+                       <para>This application will play the sounds that correspond to the given <replaceable>digits</replaceable>.
+                       Optionally, a <replaceable>gender</replaceable> may be specified. This will use the language that is currently
+                       set for the channel. See the LANGUAGE() function for more information on setting the language for the channel.</para>
+               </description>
+       </application>
+       <application name="SayPhonetic" language="en_US">
+               <synopsis>
+                       Say Phonetic.
+               </synopsis>
+               <syntax>
+                       <parameter name="string" required="true" />
+               </syntax>
+               <description>
+                       <para>This application will play the sounds from the phonetic alphabet that correspond to the
+                       letters in the given <replaceable>string</replaceable>.</para>
+               </description>
+       </application>
+       <application name="Set" language="en_US">
+               <synopsis>
+                       Set channel variable or function value.
+               </synopsis>
+               <syntax argsep="=">
+                       <parameter name="name" required="true" />
+                       <parameter name="value" required="true" />
+               </syntax>
+               <description>
+                       <para>This function can be used to set the value of channel variables or dialplan functions.
+                       When setting variables, if the variable name is prefixed with <literal>_</literal>,
+                       the variable will be inherited into channels created from the current channel.
+                       If the variable name is prefixed with <literal>__</literal>, the variable will be
+                       inherited into channels created from the current channel and all children channels.</para>
+                       <note><para>If (and only if), in <filename>/etc/asterisk/asterisk.conf</filename>, you have
+                       a <literal>[compat]</literal> category, and you have <literal>app_set = 1.6</literal> under that,then
+                       the behavior of this app changes, and does not strip surrounding quotes from the right hand side as
+                       it did previously in 1.4. The <literal>app_set = 1.6</literal> is only inserted if <literal>make samples</literal>
+                       is executed, or if users insert this by hand into the <filename>asterisk.conf</filename> file.
+                       The advantages of not stripping out quoting, and not caring about the separator characters (comma and vertical bar)
+                       were sufficient to make these changes in 1.6. Confusion about how many backslashes would be needed to properly
+                       protect separators and quotes in various database access strings has been greatly
+                       reduced by these changes.</para></note>
+               </description>
+       </application>
+       <application name="MSet" language="en_US">
+               <synopsis>
+                       Set channel variable(s) or function value(s).
+               </synopsis>
+               <syntax>
+                       <parameter name="set1" required="true" argsep="=">
+                               <argument name="name1" required="true" />
+                               <argument name="value1" required="true" />
+                       </parameter>
+                       <parameter name="set2" multiple="true" argsep="=">
+                               <argument name="name2" required="true" />
+                               <argument name="value2" required="true" />
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>This function can be used to set the value of channel variables or dialplan functions.
+                       When setting variables, if the variable name is prefixed with <literal>_</literal>,
+                       the variable will be inherited into channels created from the current channel
+                       If the variable name is prefixed with <literal>__</literal>, the variable will be
+                       inherited into channels created from the current channel and all children channels.
+                       MSet behaves in a similar fashion to the way Set worked in 1.2/1.4 and is thus
+                       prone to doing things that you may not expect. For example, it strips surrounding
+                       double-quotes from the right-hand side (value). If you need to put a separator
+                       character (comma or vert-bar), you will need to escape them by inserting a backslash
+                       before them. Avoid its use if possible.</para>
+               </description>
+       </application>
+       <application name="SetAMAFlags" language="en_US">
+               <synopsis>
+                       Set the AMA Flags.
+               </synopsis>
+               <syntax>
+                       <parameter name="flag" />
+               </syntax>
+               <description>
+                       <para>This application will set the channel's AMA Flags for billing purposes.</para>
+               </description>
+       </application>
+       <application name="Wait" language="en_US">
+               <synopsis>
+                       Waits for some time.
+               </synopsis>
+               <syntax>
+                       <parameter name="seconds" required="true">
+                               <para>Can be passed with fractions of a second. For example, <literal>1.5</literal> will ask the
+                               application to wait for 1.5 seconds.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>This application waits for a specified number of <replaceable>seconds</replaceable>.</para>
+               </description>
+       </application>
+       <application name="WaitExten" language="en_US">
+               <synopsis>
+                       Waits for an extension to be entered.
+               </synopsis>
+               <syntax>
+                       <parameter name="seconds">
+                               <para>Can be passed with fractions of a second. For example, <literal>1.5</literal> will ask the
+                               application to wait for 1.5 seconds.</para>
+                       </parameter>
+                       <parameter name="options">
+                               <optionlist>
+                                       <option name="m">
+                                               <para>Provide music on hold to the caller while waiting for an extension.</para>
+                                               <argument name="x">
+                                                       <para>Specify the class for music on hold.</para>
+                                               </argument>
+                                       </option>
+                               </optionlist>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>This application waits for the user to enter a new extension for a specified number
+                       of <replaceable>seconds</replaceable>.</para>
+               </description>
+               <see-also>
+                       <ref type="application">Playback</ref>
+                       <ref type="application">Background</ref>
+               </see-also>
+       </application>
+       <function name="EXCEPTION" language="en_US">
+               <synopsis>
+                       Retrieve the details of the current dialplan exception.
+               </synopsis>
+               <syntax>
+                       <parameter name="field" required="true">
+                               <para>The following fields are available for retrieval:</para>
+                               <enumlist>
+                                       <enum name="reason">
+                                               <para>INVALID, ERROR, RESPONSETIMEOUT, ABSOLUTETIMEOUT, or custom
+                                               value set by the RaiseException() application</para>
+                                       </enum>
+                                       <enum name="context">
+                                               <para>The context executing when the exception occurred.</para>
+                                       </enum>
+                                       <enum name="exten">
+                                               <para>The extension executing when the exception occurred.</para>
+                                       </enum>
+                                       <enum name="priority">
+                                               <para>The numeric priority executing when the exception occurred.</para>
+                                       </enum>
+                               </enumlist>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Retrieve the details (specified <replaceable>field</replaceable>) of the current dialplan exception.</para>
+               </description>
+       </function>
+ ***/
+
 #ifdef LOW_MEMORY
 #define EXT_DATA_SIZE 256
 #else
@@ -220,12 +755,17 @@ struct ast_context {
        char name[0];                           /*!< Name of the context */
 };
 
-
 /*! \brief ast_app: A registered application */
 struct ast_app {
        int (*execute)(struct ast_channel *chan, void *data);
-       const char *synopsis;                   /*!< Synopsis text for 'show applications' */
-       const char *description;                /*!< Description (help text) for 'show application &lt;name&gt;' */
+       AST_DECLARE_STRING_FIELDS(
+               AST_STRING_FIELD(synopsis);     /*!< Synopsis text for 'show applications' */
+               AST_STRING_FIELD(description);  /*!< Description (help text) for 'show application &lt;name&gt;' */
+               AST_STRING_FIELD(syntax);       /*!< Syntax text for 'core show applications' */
+               AST_STRING_FIELD(arguments);    /*!< Arguments description */
+               AST_STRING_FIELD(seealso);      /*!< See also */
+       );
+       enum ast_doc_src docsrc;/*!< Where the documentation come from. */
        AST_RWLIST_ENTRY(ast_app) list;         /*!< Next app in list */
        struct ast_module *module;              /*!< Module this app belongs to */
        char name[0];                           /*!< Name of the application */
@@ -281,6 +821,42 @@ struct pbx_exception {
        int priority;                           /*!< Priority associated with this exception */
 };
 
+#ifdef AST_XML_DOCS
+/*! \brief Default documentation language. */
+static const char default_documentation_language[] = "en_US";
+
+/*! \brief Number of columns to print when showing the XML documentation with a 
+ *         'core show application/function *' CLI command. Used in text wrapping.*/
+static const int xmldoc_text_columns = 74;
+
+/*! \brief This is a value that we will use to let the wrapping mechanism move the cursor
+ *         backward and forward xmldoc_max_diff positions before cutting the middle of a
+ *         word, trying to find a space or a \n. */
+static const int xmldoc_max_diff = 5;
+
+/*! \brief XML documentation language. */
+static char documentation_language[6];
+
+/*! \brief XML documentation tree */
+struct documentation_tree {
+       char *filename;                                 /*!< XML document filename. */
+       struct ast_xml_doc *doc;                        /*!< Open document pointer. */
+       AST_RWLIST_ENTRY(documentation_tree) entry;
+};
+
+/*!
+ * \brief Container of documentation trees
+ *
+ * \note A RWLIST is a sufficient container type to use here for now.
+ *       However, some changes will need to be made to implement ref counting
+ *       if reload support is added in the future.
+ */
+static AST_RWLIST_HEAD_STATIC(xmldoc_tree, documentation_tree);
+#endif
+
+/*! \brief Maximum number of characters needed for a color escape sequence, plus a null char */
+#define MAX_ESCAPE_CHARS   23
+
 static int pbx_builtin_answer(struct ast_channel *, void *);
 static int pbx_builtin_goto(struct ast_channel *, void *);
 static int pbx_builtin_hangup(struct ast_channel *, void *);
@@ -326,6 +902,9 @@ static unsigned int hashtab_hash_extens(const void *obj);
 static unsigned int hashtab_hash_priority(const void *obj);
 static unsigned int hashtab_hash_labels(const void *obj);
 static void __ast_internal_context_destroy( struct ast_context *con);
+#ifdef AST_XML_DOCS
+static char *xmldoc_colorization(const char *bwinput);
+#endif
 
 /* a func for qsort to use to sort a char array */
 static int compare_char(const void *a, const void *b)
@@ -433,296 +1012,38 @@ static AST_RWLIST_HEAD_STATIC(acf_root, ast_custom_function);
 static struct pbx_builtin {
        char name[AST_MAX_APP];
        int (*execute)(struct ast_channel *chan, void *data);
-       char *synopsis;
-       char *description;
 } builtins[] =
 {
        /* These applications are built into the PBX core and do not
           need separate modules */
 
-       { "Answer", pbx_builtin_answer,
-       "Answer a channel if ringing",
-       "  Answer([delay]): If the call has not been answered, this application will\n"
-       "answer it. Otherwise, it has no effect on the call. If a delay is specified,\n"
-       "Asterisk will wait this number of milliseconds before returning to\n"
-       "the dialplan after answering the call.\n"
-       },
-
-       { "BackGround", pbx_builtin_background,
-       "Play an audio file while waiting for digits of an extension to go to.",
-       "  Background(filename1[&filename2...][,options[,langoverride][,context]]):\n"
-       "This application will play the given list of files (do not put extension)\n"
-       "while waiting for an extension to be dialed by the calling channel. To\n"
-       "continue waiting for digits after this application has finished playing\n"
-       "files, the WaitExten application should be used. The 'langoverride' option\n"
-       "explicitly specifies which language to attempt to use for the requested sound\n"
-       "files. If a 'context' is specified, this is the dialplan context that this\n"
-       "application will use when exiting to a dialed extension."
-       "  If one of the requested sound files does not exist, call processing will be\n"
-       "terminated.\n"
-       "  Options:\n"
-       "    s - Causes the playback of the message to be skipped\n"
-       "          if the channel is not in the 'up' state (i.e. it\n"
-       "          hasn't been answered yet). If this happens, the\n"
-       "          application will return immediately.\n"
-       "    n - Don't answer the channel before playing the files.\n"
-       "    m - Only break if a digit hit matches a one digit\n"
-       "          extension in the destination context.\n"
-       "This application sets the following channel variable upon completion:\n"
-       " BACKGROUNDSTATUS    The status of the background attempt as a text string, one of\n"
-       "               SUCCESS | FAILED\n"
-       "See Also: Playback (application) -- Play sound file(s) to the channel,\n"
-       "                                    that cannot be interrupted\n"
-       },
-
-       { "Busy", pbx_builtin_busy,
-       "Indicate the Busy condition",
-       "  Busy([timeout]): This application will indicate the busy condition to\n"
-       "the calling channel. If the optional timeout is specified, the calling channel\n"
-       "will be hung up after the specified number of seconds. Otherwise, this\n"
-       "application will wait until the calling channel hangs up.\n"
-       },
-
-       { "Congestion", pbx_builtin_congestion,
-       "Indicate the Congestion condition",
-       "  Congestion([timeout]): This application will indicate the congestion\n"
-       "condition to the calling channel. If the optional timeout is specified, the\n"
-       "calling channel will be hung up after the specified number of seconds.\n"
-       "Otherwise, this application will wait until the calling channel hangs up.\n"
-       },
-
-       { "ExecIfTime", pbx_builtin_execiftime,
-       "Conditional application execution based on the current time",
-       "  ExecIfTime(<times>,<weekdays>,<mdays>,<months>?appname[(appargs)]):\n"
-       "This application will execute the specified dialplan application, with optional\n"
-       "arguments, if the current time matches the given time specification.\n"
-       },
-
-       { "Goto", pbx_builtin_goto,
-       "Jump to a particular priority, extension, or context",
-       "  Goto([[context,]extension,]priority): This application will set the current\n"
-       "context, extension, and priority in the channel structure. After it completes, the\n"
-       "pbx engine will continue dialplan execution at the specified location.\n"
-       "If no specific extension, or extension and context, are specified, then this\n"
-       "application will just set the specified priority of the current extension.\n"
-       "  At least a priority is required as an argument, or the goto will return a -1,\n"
-       "and the channel and call will be terminated.\n"
-       "  If the location that is put into the channel information is bogus, and asterisk cannot\n"
-       "find that location in the dialplan,\n"
-       "then the execution engine will try to find and execute the code in the 'i' (invalid)\n"
-       "extension in the current context. If that does not exist, it will try to execute the\n"
-       "'h' extension. If either or neither the 'h' or 'i' extensions have been defined, the\n"
-       "channel is hung up, and the execution of instructions on the channel is terminated.\n"
-       "What this means is that, for example, you specify a context that does not exist, then\n"
-       "it will not be possible to find the 'h' or 'i' extensions, and the call will terminate!\n"
-       },
-
-       { "GotoIf", pbx_builtin_gotoif,
-       "Conditional goto",
-       "  GotoIf(condition?[labeliftrue]:[labeliffalse]): This application will set the current\n"
-       "context, extension, and priority in the channel structure based on the evaluation of\n"
-       "the given condition. After this application completes, the\n"
-       "pbx engine will continue dialplan execution at the specified location in the dialplan.\n"
-       "The channel will continue at\n"
-       "'labeliftrue' if the condition is true, or 'labeliffalse' if the condition is\n"
-       "false. The labels are specified with the same syntax as used within the Goto\n"
-       "application.  If the label chosen by the condition is omitted, no jump is\n"
-       "performed, and the execution passes to the next instruction.\n"
-       "If the target location is bogus, and does not exist, the execution engine will try \n"
-       "to find and execute the code in the 'i' (invalid)\n"
-       "extension in the current context. If that does not exist, it will try to execute the\n"
-       "'h' extension. If either or neither the 'h' or 'i' extensions have been defined, the\n"
-       "channel is hung up, and the execution of instructions on the channel is terminated.\n"
-       "Remember that this command can set the current context, and if the context specified\n"
-       "does not exist, then it will not be able to find any 'h' or 'i' extensions there, and\n"
-       "the channel and call will both be terminated!\n"
-       },
-
-       { "GotoIfTime", pbx_builtin_gotoiftime,
-       "Conditional Goto based on the current time",
-       "  GotoIfTime(<times>,<weekdays>,<mdays>,<months>?[labeliftrue]:[labeliffalse]):\n"
-       "This application will set the context, extension, and priority in the channel structure\n"
-       "based on the evaluation of the given time specification. After this application completes,\n"
-       "the pbx engine will continue dialplan execution at the specified location in the dialplan.\n"
-       "If the current time is within the given time specification, the channel will continue at\n"
-       "'labeliftrue'. Otherwise the channel will continue at 'labeliffalse'. If the label chosen\n"
-       "by the condition is omitted, no jump is performed, and execution passes to the next\n"
-       "instruction. If the target jump location is bogus, the same actions would be taken as for\n"
-       "Goto.\n"
-       "Further information on the time specification can be found in examples\n"
-       "illustrating how to do time-based context includes in the dialplan.\n"
-       },
-
-       { "ImportVar", pbx_builtin_importvar,
-       "Import a variable from a channel into a new variable",
-       "  ImportVar(newvar=channelname,variable): This application imports a variable\n"
-       "from the specified channel (as opposed to the current one) and stores it as\n"
-       "a variable in the current channel (the channel that is calling this\n"
-       "application). Variables created by this application have the same inheritance\n"
-       "properties as those created with the Set application. See the documentation for\n"
-       "Set for more information.\n"
-       },
-
-       { "Hangup", pbx_builtin_hangup,
-       "Hang up the calling channel",
-       "  Hangup([causecode]): This application will hang up the calling channel.\n"
-       "If a causecode is given the channel's hangup cause will be set to the given\n"
-       "value.\n"
-       },
-
-       { "Incomplete", pbx_builtin_incomplete,
-       "returns AST_PBX_INCOMPLETE value",
-       "  Incomplete([n]): Signals the PBX routines that the previous matched extension\n"
-       "is incomplete and that further input should be allowed before matching can\n"
-       "be considered to be complete.  Can be used within a pattern match when\n"
-       "certain criteria warrants a longer match.\n"
-       "  If the 'n' option is specified, then Incomplete will not attempt to answer\n"
-       "the channel first.  Note that most channel types need to be in Answer state\n"
-       "in order to receive DTMF.\n"
-       },
-
-       { "KeepAlive", pbx_builtin_keepalive,
-       "returns AST_PBX_KEEPALIVE value",
-       "  KeepAlive(): This application is chiefly meant for internal use with Gosubs.\n"
-       "Please do not run it alone from the dialplan!\n"
-       },
-
-       { "NoOp", pbx_builtin_noop,
-       "Do Nothing (No Operation)",
-       "  NoOp(): This application does nothing. However, it is useful for debugging\n"
-       "purposes. Any text that is provided as arguments to this application can be\n"
-       "viewed at the Asterisk CLI. This method can be used to see the evaluations of\n"
-       "variables or functions without having any effect. Alternatively, see the\n"
-               "Verbose() application for finer grain control of output at custom verbose levels.\n"
-       },
-       
-       { "Proceeding", pbx_builtin_proceeding,
-       "Indicate proceeding",
-       "  Proceeding(): This application will request that a proceeding message\n"
-       "be provided to the calling channel.\n"
-       },
-       
-       { "Progress", pbx_builtin_progress,
-       "Indicate progress",
-       "  Progress(): This application will request that in-band progress information\n"
-       "be provided to the calling channel.\n"
-       },
-
-       { "RaiseException", pbx_builtin_raise_exception,
-       "Handle an exceptional condition",
-       "  RaiseException(<reason>): This application will jump to the \"e\" extension\n"
-       "in the current context, setting the dialplan function EXCEPTION(). If the \"e\"\n"
-       "extension does not exist, the call will hangup.\n"
-       },
-
-       { "ResetCDR", pbx_builtin_resetcdr,
-       "Resets the Call Data Record",
-       "  ResetCDR([options]):  This application causes the Call Data Record to be\n"
-       "reset.\n"
-       "  Options:\n"
-       "    w -- Store the current CDR record before resetting it.\n"
-       "    a -- Store any stacked records.\n"
-       "    v -- Save CDR variables.\n"
-       "    e -- Enable CDR only (negate effects of NoCDR).\n"
-       },
-
-       { "Ringing", pbx_builtin_ringing,
-       "Indicate ringing tone",
-       "  Ringing(): This application will request that the channel indicate a ringing\n"
-       "tone to the user.\n"
-       },
-
-       { "SayAlpha", pbx_builtin_saycharacters,
-       "Say Alpha",
-       "  SayAlpha(string): This application will play the sounds that correspond to\n"
-       "the letters of the given string.\n"
-       },
-
-       { "SayDigits", pbx_builtin_saydigits,
-       "Say Digits",
-       "  SayDigits(digits): This application will play the sounds that correspond\n"
-       "to the digits of the given number. This will use the language that is currently\n"
-       "set for the channel. See the LANGUAGE function for more information on setting\n"
-       "the language for the channel.\n"
-       },
-
-       { "SayNumber", pbx_builtin_saynumber,
-       "Say Number",
-       "  SayNumber(digits[,gender]): This application will play the sounds that\n"
-       "correspond to the given number. Optionally, a gender may be specified.\n"
-       "This will use the language that is currently set for the channel. See the\n"
-       "LANGUAGE function for more information on setting the language for the channel.\n"
-       },
-
-       { "SayPhonetic", pbx_builtin_sayphonetic,
-       "Say Phonetic",
-       "  SayPhonetic(string): This application will play the sounds from the phonetic\n"
-       "alphabet that correspond to the letters in the given string.\n"
-       },
-
-       { "Set", pbx_builtin_setvar,
-       "Set channel variable or function value",
-       "  Set(name=value)\n"
-       "This function can be used to set the value of channel variables or dialplan\n"
-       "functions. When setting variables, if the variable name is prefixed with _,\n"
-       "the variable will be inherited into channels created from the current\n"
-       "channel. If the variable name is prefixed with __, the variable will be\n"
-       "inherited into channels created from the current channel and all children\n"
-       "channels.\n"
-       "Compatibility note: If (and only if), in /etc/asterisk/asterisk.conf, you have a [compat]\n"
-    "category, and you have app_set = 1.6 under that, then the behavior of this\n"
-    "app changes, and does not strip surrounding quotes from the right hand side\n"
-    "as it did previously in 1.4. The app_set = 1.6 is only inserted if 'make samples'\n"
-       "is executed, or if users insert this by hand into the asterisk.conf file.\n"
-       "/nThe advantages of not stripping out quoting, and not caring about the\n"
-       "separator characters (comma and vertical bar) were sufficient to make these\n"
-       "changes in 1.6. Confusion about how many backslashes would be needed to properly\n"
-       "protect separators and quotes in various database access strings has been greatly\n"
-       "reduced by these changes.\n"
-       },
-
-       { "MSet", pbx_builtin_setvar_multiple,
-       "Set channel variable(s) or function value(s)",
-       "  MSet(name1=value1,name2=value2,...)\n"
-       "This function can be used to set the value of channel variables or dialplan\n"
-       "functions. When setting variables, if the variable name is prefixed with _,\n"
-       "the variable will be inherited into channels created from the current\n"
-       "channel. If the variable name is prefixed with __, the variable will be\n"
-       "inherited into channels created from the current channel and all children\n"
-       "channels.\n\n"
-       "MSet behaves in a similar fashion to the way Set worked in 1.2/1.4 and is thus\n"
-       "prone to doing things that you may not expect. For example, it strips surrounding\n"
-       "double-quotes from the right-hand side (value). If you need to put a separator\n"
-        "character (comma or vert-bar), you will need to escape them by inserting a backslash\n"
-       "before them. Avoid its use if possible.\n"
-       },
-
-       { "SetAMAFlags", pbx_builtin_setamaflags,
-       "Set the AMA Flags",
-       "  SetAMAFlags([flag]): This application will set the channel's AMA Flags for\n"
-       "  billing purposes.\n"
-       },
-
-       { "Wait", pbx_builtin_wait,
-       "Waits for some time",
-       "  Wait(seconds): This application waits for a specified number of seconds.\n"
-       "Then, dialplan execution will continue at the next priority.\n"
-       "  Note that the seconds can be passed with fractions of a second. For example,\n"
-       "'1.5' will ask the application to wait for 1.5 seconds.\n"
-       },
-
-       { "WaitExten", pbx_builtin_waitexten,
-       "Waits for an extension to be entered",
-       "  WaitExten([seconds][,options]): This application waits for the user to enter\n"
-       "a new extension for a specified number of seconds.\n"
-       "  Note that the seconds can be passed with fractions of a second. For example,\n"
-       "'1.5' will ask the application to wait for 1.5 seconds.\n"
-       "  Options:\n"
-       "    m[(x)] - Provide music on hold to the caller while waiting for an extension.\n"
-       "               Optionally, specify the class for music on hold within parenthesis.\n"
-       "See Also: Playback(application), Background(application).\n"
-       },
-
+       { "Answer",         pbx_builtin_answer },
+       { "BackGround",     pbx_builtin_background },
+       { "Busy",           pbx_builtin_busy },
+       { "Congestion",     pbx_builtin_congestion },
+       { "ExecIfTime",     pbx_builtin_execiftime },
+       { "Goto",           pbx_builtin_goto },
+       { "GotoIf",         pbx_builtin_gotoif },
+       { "GotoIfTime",     pbx_builtin_gotoiftime },
+       { "ImportVar",      pbx_builtin_importvar },
+       { "Hangup",         pbx_builtin_hangup },
+       { "Incomplete",     pbx_builtin_incomplete },
+       { "KeepAlive",      pbx_builtin_keepalive },
+       { "NoOp",           pbx_builtin_noop },
+       { "Proceeding",     pbx_builtin_proceeding },
+       { "Progress",       pbx_builtin_progress },
+       { "RaiseException", pbx_builtin_raise_exception },
+       { "ResetCDR",       pbx_builtin_resetcdr },
+       { "Ringing",        pbx_builtin_ringing },
+       { "SayAlpha",       pbx_builtin_saycharacters },
+       { "SayDigits",      pbx_builtin_saydigits },
+       { "SayNumber",      pbx_builtin_saynumber },
+       { "SayPhonetic",    pbx_builtin_sayphonetic },
+       { "Set",            pbx_builtin_setvar },
+       { "MSet",           pbx_builtin_setvar_multiple },
+       { "SetAMAFlags",    pbx_builtin_setamaflags },
+       { "Wait",           pbx_builtin_wait },
+       { "WaitExten",      pbx_builtin_waitexten }
 };
 
 static struct ast_context *contexts;
@@ -2588,195 +2909,1717 @@ int pbx_builtin_raise_exception(struct ast_channel *chan, void *vreason)
        } else
                exception = ds->data;
 
-       ast_string_field_set(exception, reason, reason);
-       ast_string_field_set(exception, context, chan->context);
-       ast_string_field_set(exception, exten, chan->exten);
-       exception->priority = chan->priority;
-       set_ext_pri(chan, "e", 0);
-       return 0;
+       ast_string_field_set(exception, reason, reason);
+       ast_string_field_set(exception, context, chan->context);
+       ast_string_field_set(exception, exten, chan->exten);
+       exception->priority = chan->priority;
+       set_ext_pri(chan, "e", 0);
+       return 0;
+}
+
+static int acf_exception_read(struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
+{
+       struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
+       struct pbx_exception *exception = NULL;
+       if (!ds || !ds->data)
+               return -1;
+       exception = ds->data;
+       if (!strcasecmp(data, "REASON"))
+               ast_copy_string(buf, exception->reason, buflen);
+       else if (!strcasecmp(data, "CONTEXT"))
+               ast_copy_string(buf, exception->context, buflen);
+       else if (!strncasecmp(data, "EXTEN", 5))
+               ast_copy_string(buf, exception->exten, buflen);
+       else if (!strcasecmp(data, "PRIORITY"))
+               snprintf(buf, buflen, "%d", exception->priority);
+       else
+               return -1;
+       return 0;
+}
+
+static struct ast_custom_function exception_function = {
+       .name = "EXCEPTION",
+       .read = acf_exception_read,
+};
+
+static char *handle_show_functions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+       struct ast_custom_function *acf;
+       int count_acf = 0;
+       int like = 0;
+
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "core show functions [like]";
+               e->usage = 
+                       "Usage: core show functions [like <text>]\n"
+                       "       List builtin functions, optionally only those matching a given string\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
+       }
+
+       if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) {
+               like = 1;
+       } else if (a->argc != 3) {
+               return CLI_SHOWUSAGE;
+       }
+
+       ast_cli(a->fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed");
+
+       AST_RWLIST_RDLOCK(&acf_root);
+       AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
+               if (!like || strstr(acf->name, a->argv[4])) {
+                       count_acf++;
+                       ast_cli(a->fd, "%-20.20s  %-35.35s  %s\n", acf->name, acf->syntax, acf->synopsis);
+               }
+       }
+       AST_RWLIST_UNLOCK(&acf_root);
+
+       ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : "");
+
+       return CLI_SUCCESS;
+}
+
+static char *handle_show_function(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+       struct ast_custom_function *acf;
+       /* Maximum number of characters added by terminal coloring is 22 */
+       char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], argtitle[40], seealsotitle[40];
+       char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *seealso = NULL;
+       char stxtitle[40], *syntax = NULL, *arguments = NULL;
+       int syntax_size, description_size, synopsis_size, arguments_size, seealso_size;
+       char *ret = NULL;
+       int which = 0;
+       int wordlen;
+
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "core show function";
+               e->usage = 
+                       "Usage: core show function <function>\n"
+                       "       Describe a particular dialplan function.\n";
+               return NULL;
+       case CLI_GENERATE:      
+               wordlen = strlen(a->word);
+               /* case-insensitive for convenience in this 'complete' function */
+               AST_RWLIST_RDLOCK(&acf_root);
+               AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
+                       if (!strncasecmp(a->word, acf->name, wordlen) && ++which > a->n) {
+                               ret = ast_strdup(acf->name);
+                               break;
+                       }
+               }
+               AST_RWLIST_UNLOCK(&acf_root);
+
+               return ret;
+       }
+
+       if (a->argc < 4) {
+               return CLI_SHOWUSAGE;
+       }
+
+       if (!(acf = ast_custom_function_find(a->argv[3]))) {
+               ast_cli(a->fd, "No function by that name registered.\n");
+               return CLI_FAILURE;
+       }
+
+       syntax_size = strlen(S_OR(acf->syntax, "Not Available")) + MAX_ESCAPE_CHARS;
+       if (!(syntax = ast_malloc(syntax_size))) {
+               ast_cli(a->fd, "Memory allocation failure!\n");
+               return CLI_FAILURE;
+       }
+
+       snprintf(info, sizeof(info), "\n  -= Info about function '%s' =- \n\n", acf->name);
+       term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle));
+       term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
+       term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
+       term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
+       term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
+       term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40);
+       term_color(syntax, S_OR(acf->syntax, "Not available"), COLOR_CYAN, 0, syntax_size);
+#ifdef AST_XML_DOCS
+       if (acf->docsrc == AST_XML_DOC) {
+               arguments = xmldoc_colorization(S_OR(acf->arguments, "Not available"));
+               synopsis = xmldoc_colorization(S_OR(acf->synopsis, "Not available"));
+               description = xmldoc_colorization(S_OR(acf->desc, "Not available"));
+               seealso = xmldoc_colorization(S_OR(acf->seealso, "Not available"));
+       } else 
+#endif
+       {
+               synopsis_size = strlen(S_OR(acf->synopsis, "Not Available")) + MAX_ESCAPE_CHARS;
+               synopsis = ast_malloc(synopsis_size);
+
+               description_size = strlen(S_OR(acf->desc, "Not Available")) + MAX_ESCAPE_CHARS;
+               description = ast_malloc(description_size);
+
+               arguments_size = strlen(S_OR(acf->arguments, "Not Available")) + MAX_ESCAPE_CHARS;
+               arguments = ast_malloc(arguments_size);
+
+               seealso_size = strlen(S_OR(acf->seealso, "Not Available")) + MAX_ESCAPE_CHARS;
+               seealso = ast_malloc(seealso_size);
+
+               /* check allocated memory. */
+               if (!synopsis || !description || !arguments || !seealso) {
+                       ast_free(synopsis);
+                       ast_free(description);
+                       ast_free(arguments);
+                       ast_free(seealso);
+                       ast_free(syntax);
+                       return CLI_FAILURE;
+               }
+
+               term_color(arguments, S_OR(acf->arguments, "Not available"), COLOR_CYAN, 0, arguments_size);
+               term_color(synopsis, S_OR(acf->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size);
+               term_color(description, S_OR(acf->desc, "Not available"), COLOR_CYAN, 0, description_size);
+               term_color(seealso, S_OR(acf->seealso, "Not available"), COLOR_CYAN, 0, seealso_size);
+       }
+
+       ast_cli(a->fd,"%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n", 
+                       infotitle, syntitle, synopsis, destitle, description, 
+                       stxtitle, syntax, argtitle, arguments, seealsotitle, seealso);
+
+       ast_free(arguments);
+       ast_free(synopsis);
+       ast_free(description);
+       ast_free(seealso);
+       ast_free(syntax);
+
+       return CLI_SUCCESS;
+}
+
+struct ast_custom_function *ast_custom_function_find(const char *name)
+{
+       struct ast_custom_function *acf = NULL;
+
+       AST_RWLIST_RDLOCK(&acf_root);
+       AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
+               if (!strcmp(name, acf->name))
+                       break;
+       }
+       AST_RWLIST_UNLOCK(&acf_root);
+
+       return acf;
+}
+
+int ast_custom_function_unregister(struct ast_custom_function *acf)
+{
+       struct ast_custom_function *cur;
+
+       if (!acf)
+               return -1;
+
+       AST_RWLIST_WRLOCK(&acf_root);
+       if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) {
+               if (cur->docsrc == AST_XML_DOC) {
+                       ast_string_field_free_memory(acf);
+               }
+               ast_verb(2, "Unregistered custom function %s\n", cur->name);
+       }
+       AST_RWLIST_UNLOCK(&acf_root);
+
+       return cur ? 0 : -1;
+}
+
+#ifdef AST_XML_DOCS
+static const struct strcolorized_tags {
+       const char *init;      /*!< Replace initial tag with this string. */
+       const char *end;       /*!< Replace end tag with this string. */
+       const int colorfg;     /*!< Foreground color. */
+       const char *inittag;   /*!< Initial tag description. */
+       const char *endtag;    /*!< Ending tag description. */
+} colorized_tags[] = {
+       { "<",  ">",  COLOR_GREEN,  "<replaceable>", "</replaceable>" },
+       { "\'", "\'", COLOR_BLUE,   "<literal>",     "</literal>" },
+       { "*",  "*",  COLOR_RED,    "<emphasis>",    "</emphasis>" },
+       { "\"", "\"", COLOR_YELLOW, "<filename>",    "</filename>" },
+       { "\"", "\"", COLOR_CYAN,   "<directory>",   "</directory>" },
+       { "${", "}",  COLOR_GREEN,  "<variable>",    "</variable>" },
+       { "",   "",   COLOR_BLUE,   "<value>",       "</value>" },
+       { "",   "",   COLOR_BLUE,   "<enum>",        "</enum>" },
+       { "\'", "\'", COLOR_GRAY,   "<astcli>",      "</astcli>" },
+
+       /* Special tags */
+       { "", "", COLOR_YELLOW, "<note>",   "</note>" },
+       { "", "", COLOR_RED,   "<warning>", "</warning>" }
+};
+
+static const struct strspecial_tags {
+       const char *tagname;            /*!< Special tag name. */
+       const char *init;               /*!< Print this at the beginning. */
+       const char *end;                /*!< Print this at the end. */
+} special_tags[] = {
+       { "note",    "<note>NOTE:</note> ",             "" },
+       { "warning", "<warning>WARNING!!!:</warning> ", "" }
+};
+
+/*! \internal
+ *  \brief Calculate the space in bytes used by a format string
+ *         that will be passed to a sprintf function.
+ *  \param postbr The format string to use to calculate the length.
+ *  \retval The postbr length.
+ */
+static int xmldoc_postbrlen(const char *postbr)
+{
+       int postbrreallen = 0, i;
+       size_t postbrlen;
+
+       if (!postbr) {
+               return 0;
+       }
+       postbrlen = strlen(postbr);
+       for (i = 0; i < postbrlen; i++) {
+               if (postbr[i] == '\t') {
+                       postbrreallen += 8 - (postbrreallen % 8);
+               } else {
+                       postbrreallen++;
+               }
+       }
+       return postbrreallen;
+}
+
+/*! \internal
+ *  \brief Setup postbr to be used while wrapping the text.
+ *         Add to postbr array all the spaces and tabs at the beginning of text.
+ *  \param postbr output array.
+ *  \param len text array length.
+ *  \param text Text with format string before the actual string.
+ */
+static void xmldoc_setpostbr(char *postbr, size_t len, const char *text)
+{
+       int c, postbrlen = 0;
+
+       if (!text) {
+               return;
+       }
+
+       for (c = 0; c < len; c++) {
+               if (text[c] == '\t' || text[c] == ' ') {
+                       postbr[postbrlen++] = text[c];
+               } else {
+                       break;
+               }
+       }
+       postbr[postbrlen] = '\0';
+}
+
+/*! \internal
+ *  \brief Try to find a space or a break in text starting at currentpost
+ *         and moving at most maxdiff positions.
+ *         Helper for xmldoc_string_wrap().
+ *  \param text Input string where it will search.
+ *  \param currentpos Current position within text.
+ *  \param maxdiff Not move more than maxdiff inside text.
+ *  \retval 1 if a space or break is found inside text while moving.
+ *  \retval 0 if no space or break is found.
+ */
+static int xmldoc_wait_nextspace(const char *text, int currentpos, int maxdiff)
+{
+       int i, textlen;
+
+       if (!text) {
+               return 0;
+       }
+
+       textlen = strlen(text);
+       for (i = currentpos; i < textlen; i++) {
+               if (text[i] == ESC) {
+                       /* Move to the end of the escape sequence */
+                       while (i < textlen && text[i] != 'm') {
+                               i++;
+                       }
+               } else if (text[i] == ' ' || text[i] == '\n') {
+                       /* Found the next space or linefeed */
+                       return 1;
+               } else if (i - currentpos > maxdiff) {
+                       /* We have looked the max distance and didn't find it */
+                       return 0;
+               }
+       }
+
+       /* Reached the end and did not find it */
+
+       return 0;
+}
+
+/*! \internal
+ *  \brief Helper function for xmldoc_string_wrap().
+ *        Try to found a space or a break inside text moving backward
+ *        not more than maxdiff positions.
+ *  \param text The input string where to search for a space.
+ *  \param currentpos The current cursor position.
+ *  \param maxdiff The max number of positions to move within text.
+ *  \retval 0 If no space is found (Notice that text[currentpos] is not a space or a break)
+ *  \retval > 0 If a space or a break is found, and the result is the position relative to
+ *             currentpos.
+ */
+static int xmldoc_foundspace_backward(const char *text, int currentpos, int maxdiff)
+{
+       int i;
+
+       for (i = currentpos; i > 0; i--) {
+               if (text[i] == ' ' || text[i] == '\n') {
+                       return (currentpos - i);
+               } else if (text[i] == 'm' && (text[i - 1] >= '0' || text[i - 1] <= '9')) {
+                       /* give up, we found the end of a possible ESC sequence. */
+                       return 0;
+               } else if (currentpos - i > maxdiff) {
+                       /* give up, we can't move anymore. */
+                       return 0;
+               }
+       }
+
+       /* we found the beginning of the text */
+
+       return 0;
+}
+
+/*! \internal
+ *  \brief Justify a text to a number of columns.
+ *  \param text Input text to be justified.
+ *  \param columns Number of columns to preserve in the text.
+ *  \param maxdiff Try to not cut a word when goinf down.
+ *  \retval NULL on error.
+ *  \retval The wrapped text.
+ */
+static char *xmldoc_string_wrap(const char *text, int columns, int maxdiff)
+{
+       struct ast_str *tmp;
+       char *ret, postbr[160];
+       int count = 1, i, backspace, needtobreak = 0, colmax, textlen;
+
+       /* sanity check */
+       if (!text || columns <= 0 || maxdiff < 0) {
+               ast_log(LOG_WARNING, "Passing wrong arguments while trying to wrap the text\n");
+               return NULL;
+       }
+
+       tmp = ast_str_create(strlen(text) * 3);
+
+       if (!tmp) {
+               return NULL;
+       }
+
+       /* Check for blanks and tabs and put them in postbr. */
+       xmldoc_setpostbr(postbr, sizeof(postbr), text);
+       colmax = columns - xmldoc_postbrlen(postbr);
+
+       textlen = strlen(text);
+       for (i = 0; i < textlen; i++) {
+               if (needtobreak || !(count % colmax)) {
+                       if (text[i] == ' ') {
+                               ast_str_append(&tmp, 0, "\n%s", postbr);
+                               needtobreak = 0;
+                               count = 1;
+                       } else if (text[i] != '\n') {
+                               needtobreak = 1;
+                               if (xmldoc_wait_nextspace(text, i, maxdiff)) {
+                                       /* wait for the next space */
+                                       ast_str_append(&tmp, 0, "%c", text[i]);
+                                       continue;
+                               }
+                               /* Try to look backwards */
+                               backspace = xmldoc_foundspace_backward(text, i, maxdiff);
+                               if (backspace) {
+                                       needtobreak = 1;
+                                       tmp->used -= backspace;
+                                       tmp->str[tmp->used] = '\0';
+                                       i -= backspace + 1;
+                                       continue;
+                               }
+                               ast_str_append(&tmp, 0, "\n%s", postbr);
+                               needtobreak = 0;
+                               count = 1;
+                       }
+                       /* skip blanks after a \n */
+                       while (text[i] == ' ') {
+                               i++;
+                       }
+               }
+               if (text[i] == '\n') {
+                       xmldoc_setpostbr(postbr, sizeof(postbr), &text[i] + 1);
+                       colmax = columns - xmldoc_postbrlen(postbr);
+                       needtobreak = 0;
+                       count = 1;
+               }
+               if (text[i] == ESC) {
+                       /* Ignore Escape sequences. */
+                       do {
+                               ast_str_append(&tmp, 0, "%c", text[i]);
+                               i++;
+                       } while (i < textlen && text[i] != 'm');
+               } else {
+                       count++;
+               }
+               ast_str_append(&tmp, 0, "%c", text[i]);
+       }
+
+       ret = ast_strdup(tmp->str);
+       ast_free(tmp);
+
+       return ret;
+}
+
+/*! \internal
+ *  \brief Colorize the xmldoc output.
+ *  \param bwinput Not colorized input.
+ *  \retval NULL on error.
+ *  \retval New malloced buffer colorized.
+ */
+static char *xmldoc_colorization(const char *bwinput)
+{
+       struct ast_str *colorized;
+       char *wrapped = NULL;
+       int i, c, len, colorsection;
+       char *tmp;
+       size_t bwinputlen;
+       static const int base_fg = COLOR_CYAN;
+
+       if (!bwinput) {
+               return NULL;
+       }
+
+       bwinputlen = strlen(bwinput);
+
+       if (!(colorized = ast_str_create(256))) {
+               return NULL;
+       }
+
+       ast_term_color_code(&colorized, base_fg, 0);
+       if (!colorized) {
+               return NULL;
+       }
+
+       for (i = 0; i < bwinputlen; i++) {
+               colorsection = 0;
+               /* Check if we are at the beginning of a tag to be colorized. */
+               for (c = 0; c < ARRAY_LEN(colorized_tags); c++) {
+                       if (strncasecmp(bwinput + i, colorized_tags[c].inittag, strlen(colorized_tags[c].inittag))) {
+                               continue;
+                       }
+                       
+                       if (!(tmp = strcasestr(bwinput + i + strlen(colorized_tags[c].inittag), colorized_tags[c].endtag))) {
+                               continue;
+                       }
+
+                       len = tmp - (bwinput + i + strlen(colorized_tags[c].inittag));
+
+                       /* Setup color */
+                       ast_term_color_code(&colorized, colorized_tags[c].colorfg, 0);
+                       if (!colorized) {
+                               return NULL;
+                       }
+
+                       /* copy initial string replace */
+                       ast_str_append(&colorized, 0, "%s", colorized_tags[c].init);
+                       if (!colorized) {
+                               return NULL;
+                       }
+                       {
+                               char buf[len + 1];
+                               ast_copy_string(buf, bwinput + i + strlen(colorized_tags[c].inittag), sizeof(buf));
+                               ast_str_append(&colorized, 0, "%s", buf);
+                       }
+                       if (!colorized) {
+                               return NULL;
+                       }
+
+                       /* copy the ending string replace */
+                       ast_str_append(&colorized, 0, "%s", colorized_tags[c].end);
+                       if (!colorized) {
+                               return NULL;
+                       }
+
+                       /* Continue with the last color. */
+                       ast_term_color_code(&colorized, base_fg, 0);
+                       if (!colorized) {
+                               return NULL;
+                       }
+
+                       i += len + strlen(colorized_tags[c].endtag) + strlen(colorized_tags[c].inittag) - 1;
+                       colorsection = 1;
+                       break;
+               }
+
+               if (!colorsection) {
+                       ast_str_append(&colorized, 0, "%c", bwinput[i]);
+                       if (!colorized) {
+                               return NULL;
+                       }
+               }
+       }
+
+       ast_term_color_code(&colorized, COLOR_BRWHITE, 0);
+       if (!colorized) {
+               return NULL;
+       }
+
+       /* Wrap the text, notice that string wrap will avoid cutting an ESC sequence. */
+       wrapped = xmldoc_string_wrap(colorized->str, xmldoc_text_columns, xmldoc_max_diff);
+
+       ast_free(colorized);
+
+       return wrapped;
+}
+
+/*! \internal
+ *  \brief Cleanup spaces and tabs after a \n
+ *  \param text String to be cleaned up.
+ *  \param output buffer (not already allocated).
+ *  \param lastspaces Remove last spaces in the string.
+ */
+static void xmldoc_string_cleanup(const char *text, struct ast_str **output, int lastspaces)
+{
+       int i;
+       size_t textlen;
+
+       if (!text) {
+               *output = NULL;
+               return;
+       }
+       
+       textlen = strlen(text);
+
+       *output = ast_str_create(textlen);
+       if (!(*output)) {
+               ast_log(LOG_ERROR, "Problem allocating output buffer\n");
+               return;
+       }
+
+       for (i = 0; i < textlen; i++) {
+               if (text[i] == '\n' || text[i] == '\r') {
+                       /* remove spaces/tabs/\n after a \n. */
+                       while (text[i + 1] == '\t' || text[i + 1] == '\r' || text[i + 1] == '\n') {
+                               i++;
+                       }
+                       ast_str_append(output, 0, " ");
+                       continue;
+               } else {
+                       ast_str_append(output, 0, "%c", text[i]);
+               }
+       }
+
+       /* remove last spaces (we dont want always to remove the trailing spaces). */
+       if (lastspaces) {
+               ast_str_trim_blanks(*output);
+       }
+}
+
+/*! \internal
+ *  \brief Get the application/function node for 'name' application/function with language 'language'
+ *         if we don't find any, get the first application with 'name' no matter which language with.
+ *  \param type 'application', 'function', ...
+ *  \param name Application or Function name.
+ *  \param language Try to get this language (if not found try with en_US)
+ *  \retval NULL on error.
+ *  \retval A node of type ast_xml_node.
+ */
+static struct ast_xml_node *xmldoc_get_node(const char *type, const char *name, const char *language)
+{
+       struct ast_xml_node *node = NULL;
+       struct documentation_tree *doctree;
+       const char *lang;
+
+       AST_RWLIST_RDLOCK(&xmldoc_tree);
+       AST_LIST_TRAVERSE(&xmldoc_tree, doctree, entry) {
+               /* the core xml documents have priority over thirdparty document. */
+               node = ast_xml_get_root(doctree->doc);
+               while ((node = ast_xml_find_element(node, type, "name", name))) {
+                       /* Check language */
+                       lang = ast_xml_get_attribute(node, "language");
+                       if (lang && !strcmp(lang, language)) {
+                               ast_xml_free_attr(lang);
+                               break;
+                       } else if (lang) {
+                               ast_xml_free_attr(lang);
+                       }
+               }
+
+               if (node && ast_xml_node_get_children(node)) {
+                       break;
+               }
+
+               /* We didn't find the application documentation for the specified language,
+               so, try to load documentation for any language */
+               node = ast_xml_get_root(doctree->doc);
+               if (ast_xml_node_get_children(node)) {
+                       if ((node = ast_xml_find_element(ast_xml_node_get_children(node), type, "name", name))) {
+                               break;
+                       }
+               }
+       }
+       AST_RWLIST_UNLOCK(&xmldoc_tree);
+
+       return node;
+}
+
+/*! \internal
+ *  \brief Helper function used to build the syntax, it allocates the needed buffer (or reallocates it),
+ *         and based on the reverse value it makes use of fmt to print the parameter list inside the 
+ *         realloced buffer (syntax).
+ *  \param reverse We are going backwards while generating the syntax?
+ *  \param len Current length of 'syntax' buffer.
+ *  \param syntax Output buffer for the concatenated values.
+ *  \param fmt A format string that will be used in a sprintf call.
+ */
+static __attribute__((format(printf,4,5))) void xmldoc_reverse_helper(int reverse, int *len, char **syntax, const char *fmt, ...)
+{
+       int totlen, tmpfmtlen;
+       char *tmpfmt, tmp;
+       va_list ap;
+
+       va_start(ap, fmt);
+       if (ast_vasprintf(&tmpfmt, fmt, ap) < 0) {
+               va_end(ap);
+               return;
+       }
+       va_end(ap);
+
+       tmpfmtlen = strlen(tmpfmt);
+       totlen = *len + tmpfmtlen + 1;
+
+       *syntax = ast_realloc(*syntax, totlen);
+
+       if (!*syntax) {
+               ast_free(tmpfmt);
+               return;
+       }
+
+       if (reverse) {
+               memmove(*syntax + tmpfmtlen, *syntax, *len);
+               /* Save this char, it will be overwritten by the \0 of strcpy. */
+               tmp = (*syntax)[0];
+               strcpy(*syntax, tmpfmt);
+               /* Restore the already saved char. */
+               (*syntax)[tmpfmtlen] = tmp;
+               (*syntax)[totlen - 1] = '\0';
+       } else {
+               strcpy(*syntax + *len, tmpfmt);
+       }
+
+       *len = totlen - 1;
+       ast_free(tmpfmt);
+}
+
+/*! \internal
+ *  \brief Check if the passed node has <argument> tags inside it.
+ *  \param node Root node to search argument elements.
+ *  \retval 1 If a <argument> element is found inside 'node'.
+ *  \retval 0 If no <argument> is found inside 'node'.
+ */
+static int xmldoc_has_arguments(struct ast_xml_node *fixnode)
+{
+       struct ast_xml_node *node = fixnode;
+
+       for (node = ast_xml_node_get_children(fixnode); node; node = ast_xml_node_get_next(node)) {
+               if (!strcasecmp(ast_xml_node_get_name(node), "argument")) {
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+/*! \internal
+ *  \brief Build the syntax for a specified starting node.
+ *  \param rootnode A pointer to the ast_xml root node.
+ *  \param rootname Name of the application, function, option, etc. to build the syntax.
+ *  \param childname The name of each parameter node.
+ *  \param printparenthesis Boolean if we must print parenthesis if not parameters are found in the rootnode.
+ *  \param printrootname Boolean if we must print the rootname before the syntax and parenthesis at the begining/end.
+ *  \retval NULL on error.
+ *  \retval An ast_malloc'ed string with the syntax generated.
+ */
+static char *xmldoc_get_syntax(struct ast_xml_node *rootnode, const char *rootname, const char *childname, int printparenthesis, int printrootname)
+{
+#define GOTONEXT(__rev, __a) (__rev ? ast_xml_node_get_prev(__a) : ast_xml_node_get_next(__a))
+#define ISLAST(__rev, __a)  (__rev == 1 ? (ast_xml_node_get_prev(__a) ? 0 : 1) : (ast_xml_node_get_next(__a) ? 0 : 1))
+#define MP(__a) ((multiple ? __a : ""))
+       struct ast_xml_node *node = NULL, *firstparam = NULL, *lastparam = NULL;
+       const char *paramtype, *multipletype, *paramname, *attrargsep, *parenthesis, *argname;
+       int reverse, required, paramcount = 0, openbrackets = 0, len = 0, hasparams=0;
+       int reqfinode = 0, reqlanode = 0, optmidnode = 0, prnparenthesis;
+       char *syntax = NULL, *argsep;
+       int paramnamemalloc, multiple;
+
+       if (ast_strlen_zero(rootname) || ast_strlen_zero(childname)) {
+               ast_log(LOG_WARNING, "Tried to look in XML tree with faulty rootname or childname while creating a syntax.\n");
+               return NULL;
+       }
+
+       if (!rootnode || !ast_xml_node_get_children(rootnode)) {
+               /* If the rootnode field is not found, at least print name. */
+               ast_asprintf(&syntax, "%s%s", (printrootname ? rootname : ""), (printparenthesis ? "()" : ""));
+               return syntax;
+       }
+
+       /* Get the argument separator from the root node attribute name 'argsep', if not found
+       defaults to ','. */
+       attrargsep = ast_xml_get_attribute(rootnode, "argsep");
+       if (attrargsep) {
+               argsep = ast_strdupa(attrargsep);
+               ast_xml_free_attr(attrargsep);
+       } else {
+               argsep = ast_strdupa(",");
+       }
+
+       /* Get order of evaluation. */
+       for (node = ast_xml_node_get_children(rootnode); node; node = ast_xml_node_get_next(node)) {
+               if (strcasecmp(ast_xml_node_get_name(node), childname)) {
+                       continue;
+               }
+               required = 0;
+               hasparams = 1;
+               if ((paramtype = ast_xml_get_attribute(node, "required"))) {
+                       if (ast_true(paramtype)) {
+                               required = 1;
+                       }
+                       ast_xml_free_attr(paramtype);
+               }
+
+               lastparam = node;
+               reqlanode = required;
+
+               if (!firstparam) {
+                       /* first parameter node */
+                       firstparam = node;
+                       reqfinode = required;
+               }
+       }
+
+       if (!hasparams) {
+               /* This application, function, option, etc, doesn't have any params. */
+               ast_asprintf(&syntax, "%s%s", (printrootname ? rootname : ""), (printparenthesis ? "()" : ""));
+               return syntax;
+       }
+
+       if (reqfinode && reqlanode) {
+               /* check midnode */
+               for (node = ast_xml_node_get_children(rootnode); node; node = ast_xml_node_get_next(node)) {
+                       if (strcasecmp(ast_xml_node_get_name(node), childname)) {
+                               continue;
+                       }
+                       if (node != firstparam && node != lastparam) {
+                               if ((paramtype = ast_xml_get_attribute(node, "required"))) {
+                                       if (!ast_true(paramtype)) {
+                                               optmidnode = 1;
+                                               break;
+                                       }
+                                       ast_xml_free_attr(paramtype);
+                               }
+                       }
+               }
+       }
+
+       if ((!reqfinode && reqlanode) || (reqfinode && reqlanode && optmidnode)) {
+               reverse = 1;
+               node = lastparam;
+       } else {
+               reverse = 0;
+               node = firstparam;
+       }
+
+       /* init syntax string. */
+       if (reverse) {
+               xmldoc_reverse_helper(reverse, &len, &syntax,
+                       (printrootname ? (printrootname == 2 ? ")]" : ")"): ""));
+       } else {
+               xmldoc_reverse_helper(reverse, &len, &syntax, "%s%s", (printrootname ? rootname : ""),
+                       (printrootname ? (printrootname == 2 ? "[(" : "(") : ""));
+       }
+
+       for (; node; node = GOTONEXT(reverse, node)) {
+               if (strcasecmp(ast_xml_node_get_name(node), childname)) {
+                       continue;
+               }
+
+               /* Get the argument name, if it is not the leaf, go inside that parameter. */
+               if (xmldoc_has_arguments(node)) {
+                       parenthesis = ast_xml_get_attribute(node, "hasparams");
+                       prnparenthesis = 0;
+                       if (parenthesis) {
+                               prnparenthesis = ast_true(parenthesis);
+                               if (!strcasecmp(parenthesis, "optional")) {
+                                       prnparenthesis = 2;
+                               }
+                               ast_xml_free_attr(parenthesis);
+                       }
+                       argname = ast_xml_get_attribute(node, "name");
+                       if (argname) {
+                               paramname = xmldoc_get_syntax(node, argname, "argument", prnparenthesis, prnparenthesis);
+                               ast_xml_free_attr(argname);
+                               paramnamemalloc = 1;
+                       } else {
+                               /* Malformed XML, print **UNKOWN** */
+                               paramname = ast_strdup("**unknown**");
+                       }
+                       paramnamemalloc = 1;
+               } else {
+                       paramnamemalloc = 0;
+                       paramname = ast_xml_get_attribute(node, "name");
+                       if (!paramname) {
+                               ast_log(LOG_WARNING, "Malformed XML %s: no %s name\n", rootname, childname);
+                               if (syntax) {
+                                       /* Free already allocated syntax */
+                                       ast_free(syntax);
+                               }
+                               /* to give up is ok? */
+                               ast_asprintf(&syntax, "%s%s", (printrootname ? rootname : ""), (printparenthesis ? "()" : ""));
+                               return syntax;
+                       }
+               }
+
+               /* Defaults to 'false'. */
+               multiple = 0;
+               if ((multipletype = ast_xml_get_attribute(node, "multiple"))) {
+                       if (ast_true(multipletype)) {
+                               multiple = 1;
+                       }
+                       ast_xml_free_attr(multipletype);
+               }
+
+               required = 0;   /* Defaults to 'false'. */
+               if ((paramtype = ast_xml_get_attribute(node, "required"))) {
+                       if (ast_true(paramtype)) {
+                               required = 1;
+                       }
+                       ast_xml_free_attr(paramtype);
+               }
+
+               /* build syntax core. */
+
+               if (required) {
+                       /* First parameter */
+                       if (!paramcount) {
+                               xmldoc_reverse_helper(reverse, &len, &syntax, "%s%s%s%s", paramname, MP("["), MP(argsep), MP("...]"));
+                       } else {
+                               /* Time to close open brackets. */
+                               while (openbrackets > 0) {
+                                       xmldoc_reverse_helper(reverse, &len, &syntax, (reverse ? "[" : "]"));
+                                       openbrackets--;
+                               }
+                               if (reverse) {
+                                       xmldoc_reverse_helper(reverse, &len, &syntax, "%s%s", paramname, argsep);
+                               } else {
+                                       xmldoc_reverse_helper(reverse, &len, &syntax, "%s%s", argsep, paramname);
+                               }
+                               xmldoc_reverse_helper(reverse, &len, &syntax, "%s%s%s", MP("["), MP(argsep), MP("...]"));
+                       }
+               } else {
+                       /* First parameter */
+                       if (!paramcount) {
+                               xmldoc_reverse_helper(reverse, &len, &syntax, "[%s%s%s%s]", paramname, MP("["), MP(argsep), MP("...]"));
+                       } else {
+                               if (ISLAST(reverse, node)) {
+                                       /* This is the last parameter. */
+                                       if (reverse) {
+                                               xmldoc_reverse_helper(reverse, &len, &syntax, "[%s%s%s%s]%s", paramname,
+                                                                       MP("["), MP(argsep), MP("...]"), argsep);
+                                       } else {
+                                               xmldoc_reverse_helper(reverse, &len, &syntax, "%s[%s%s%s%s]", argsep, paramname,
+                                                                       MP("["), MP(argsep), MP("...]"));
+                                       }
+                               } else {
+                                       if (reverse) {
+                                               xmldoc_reverse_helper(reverse, &len, &syntax, "%s%s%s%s%s]", paramname, argsep,
+                                                                       MP("["), MP(argsep), MP("...]"));
+                                       } else {
+                                               xmldoc_reverse_helper(reverse, &len, &syntax, "[%s%s%s%s%s", argsep, paramname,
+                                                                       MP("["), MP(argsep), MP("...]"));
+                                       }
+                                       openbrackets++;
+                               }
+                       }
+               }
+               if (paramnamemalloc) {
+                       ast_free((char *) paramname);
+               } else {
+                       ast_xml_free_attr(paramname);
+               }
+
+               paramcount++;
+       }
+
+       /* Time to close open brackets. */
+       while (openbrackets > 0) {
+               xmldoc_reverse_helper(reverse, &len, &syntax, (reverse ? "[" : "]"));
+               openbrackets--;
+       }
+
+       /* close syntax string. */
+       if (reverse) {
+               xmldoc_reverse_helper(reverse, &len, &syntax, "%s%s", (printrootname ? rootname : ""), 
+                       (printrootname ? (printrootname == 2 ? "[(" : "(") : ""));
+       } else {
+               xmldoc_reverse_helper(reverse, &len, &syntax, (printrootname ? (printrootname == 2 ? ")]" : ")") : ""));
+       }
+
+       return syntax;
+#undef ISLAST
+#undef GOTONEXT
+#undef MP
+}
+
+/*! \internal
+ *  \brief Get the syntax for a specified application or function.
+ *  \param type Application or Function ?
+ *  \param name Name of the application or function.
+ *  \retval NULL on error.
+ *  \retval The generated syntax in a ast_malloc'ed string.
+ */
+static char *xmldoc_build_syntax(const char *type, const char *name)
+{
+       struct ast_xml_node *node;
+       char *syntax = NULL;
+
+       node = xmldoc_get_node(type, name, documentation_language);
+       if (!node) {
+               return NULL;
+       }
+
+       for (node = ast_xml_node_get_children(node); node; node = ast_xml_node_get_next(node)) {
+               if (!strcasecmp(ast_xml_node_get_name(node), "syntax")) {
+                       break;
+               }
+       }
+
+       if (node) {
+               syntax = xmldoc_get_syntax(node, name, "parameter", 1, 1);
+       }
+       return syntax;
+}
+
+/*! \internal
+ *  \brief Parse a <para> element.
+ *  \param node The <para> element pointer.
+ *  \param tabs Added this string before the content of the <para> element.
+ *  \param posttabs Added this string after the content of the <para> element.
+ *  \param buffer This must be an already allocated ast_str. It will be used
+ *         to store the result (if already has something it will be appended to the current
+ *         string).
+ *  \retval 1 If 'node' is a named 'para'.
+ *  \retval 2 If data is appended in buffer.
+ *  \retval 0 on error.
+ */
+static int xmldoc_parse_para(struct ast_xml_node *node, const char *tabs, const char *posttabs, struct ast_str **buffer)
+{
+       const char *tmptext;
+       struct ast_xml_node *tmp;
+       int ret = 0;
+       struct ast_str *tmpstr;
+
+       if (!node || !ast_xml_node_get_children(node)) {
+               return ret;
+       }
+
+       if (strcasecmp(ast_xml_node_get_name(node), "para")) {
+               return ret;
+       }
+
+       ast_str_append(buffer, 0, "%s", tabs);
+
+       ret = 1;
+
+       for (tmp = ast_xml_node_get_children(node); tmp; tmp = ast_xml_node_get_next(tmp)) {
+               /* Get the text inside the <para> element and append it to buffer. */
+               tmptext = ast_xml_get_text(tmp);
+               if (tmptext) {
+                       /* Strip \n etc. */
+                       xmldoc_string_cleanup(tmptext, &tmpstr, 0);
+                       ast_xml_free_text(tmptext);
+                       if (tmpstr) {
+                               if (strcasecmp(ast_xml_node_get_name(tmp), "text")) {
+                                       ast_str_append(buffer, 0, "<%s>%s</%s>", ast_xml_node_get_name(tmp), 
+                                                       tmpstr->str, ast_xml_node_get_name(tmp));
+                               } else {
+                                       ast_str_append(buffer, 0, "%s", tmpstr->str);
+                               }
+                               ast_free(tmpstr);
+                               ret = 2;
+                       }
+               }
+       }
+
+       ast_str_append(buffer, 0, "%s", posttabs);
+
+       return ret;
+}
+
+/*! \internal
+ *  \brief Parse special elements defined in 'struct special_tags' special elements must have a <para> element inside them.
+ *  \param fixnode special tag node pointer.
+ *  \param tabs put tabs before printing the node content.
+ *  \param posttabs put posttabs after printing node content.
+ *  \param buffer Output buffer, the special tags will be appended here.
+ *  \retval 0 if no special element is parsed.
+ *  \retval 1 if a special element is parsed (data is appended to buffer).
+ *  \retval 2 if a special element is parsed and also a <para> element is parsed inside the specialtag.
+ */
+static int xmldoc_parse_specialtags(struct ast_xml_node *fixnode, const char *tabs, const char *posttabs, struct ast_str **buffer)
+{
+       struct ast_xml_node *node = fixnode;
+       int ret = 0, i, count = 0;
+
+       if (!node || !ast_xml_node_get_children(node)) {
+               return ret;
+       }
+
+       for (i = 0; i < ARRAY_LEN(special_tags); i++) {
+               if (strcasecmp(ast_xml_node_get_name(node), special_tags[i].tagname)) {
+                       continue;
+               }
+
+               ret = 1;
+               /* This is a special tag. */
+
+               /* concat data */
+               if (!ast_strlen_zero(special_tags[i].init)) {
+                       ast_str_append(buffer, 0, "%s%s", tabs, special_tags[i].init);
+               }
+
+               /* parse <para> elements inside special tags. */
+               for (node = ast_xml_node_get_children(node); node; node = ast_xml_node_get_next(node)) {
+                       /* first <para> just print it without tabs at the begining. */
+                       if (xmldoc_parse_para(node, (!count ? "" : tabs), posttabs, buffer) == 2) {
+                               ret = 2;
+                       }
+               }
+
+               if (!ast_strlen_zero(special_tags[i].end)) {
+                       ast_str_append(buffer, 0, "%s%s", special_tags[i].end, posttabs);
+               }
+
+               break;
+       }
+
+       return ret;
+}
+
+/*! \internal
+ *  \brief Parse an <argument> element from the xml documentation.
+ *  \param fixnode Pointer to the 'argument' xml node.
+ *  \param insideparameter If we are parsing an <argument> inside a <parameter>.
+ *  \param paramtabs pre tabs if we are inside a parameter element.
+ *  \param tabs What to be printed before the argument name.
+ *  \param buffer Output buffer to put values found inside the <argument> element.
+ *  \retval 1 If there is content inside the argument.
+ *  \retval 0 If the argument element is not parsed, or there is no content inside it.
+ */
+static int xmldoc_parse_argument(struct ast_xml_node *fixnode, int insideparameter, const char *paramtabs, const char *tabs, struct ast_str **buffer)
+{
+       struct ast_xml_node *node = fixnode;
+       const char *argname;
+       int count=0, ret = 0;
+
+       if (!node || !ast_xml_node_get_children(node)) {
+               return ret;
+       }
+
+       /* Print the argument names */
+       argname = ast_xml_get_attribute(node, "name");
+       if (!argname) {
+               return 0;
+       }
+       ast_str_append(buffer, 0, "%s%s%s", tabs, argname, (insideparameter ? "\n" : ""));
+       ast_xml_free_attr(argname);
+
+       for (node = ast_xml_node_get_children(node); node; node = ast_xml_node_get_next(node)) {
+               if (xmldoc_parse_para(node, (insideparameter ? paramtabs : (!count ? " - " : tabs)), "\n", buffer) == 2) {
+                       count++;
+                       ret = 1;
+               } else if (xmldoc_parse_specialtags(node, (insideparameter ? paramtabs : (!count ? " - " : tabs)), "\n", buffer) == 2) {
+                       count++;
+                       ret = 1;
+               }
+       }
+
+       return ret;
+}
+
+/*! \internal
+ *  \brief Parse a <variable> node inside a <variablelist> node.
+ *  \param node The variable node to parse.
+ *  \param tabs A string to be appended at the begining of the output that will be stored
+ *         in buffer.
+ *  \param buffer This must be an already created ast_str. It will be used
+ *         to store the result (if already has something it will be appended to the current
+ *         string).
+ *  \retval 0 if no data is appended.
+ *  \retval 1 if data is appended.
+ */
+static int xmldoc_parse_variable(struct ast_xml_node *node, const char *tabs, struct ast_str **buffer)
+{
+       struct ast_xml_node *tmp;
+       const char *valname;
+       const char *tmptext;
+       struct ast_str *cleanstr;
+       int ret = 0, printedpara=0;
+
+       for (tmp = ast_xml_node_get_children(node); tmp; tmp = ast_xml_node_get_next(tmp)) {
+               if (xmldoc_parse_para(tmp, (ret ? tabs : ""), "\n", buffer)) {
+                       printedpara = 1;
+                       continue;
+               } else if (xmldoc_parse_specialtags(tmp, (ret ? tabs : ""), "\n", buffer)) {
+                       printedpara = 1;
+                       continue;
+               }
+
+               if (strcasecmp(ast_xml_node_get_name(tmp), "value")) {
+                       continue;
+               }
+
+               /* Parse a <value> tag only. */
+               if (!printedpara) {
+                       ast_str_append(buffer, 0, "\n");
+                       printedpara = 1;
+               }
+               /* Parse each <value name='valuename'>desciption</value> */
+               valname = ast_xml_get_attribute(tmp, "name");
+               if (valname) {
+                       ret = 1;
+                       ast_str_append(buffer, 0, "%s<value>%s</value>", tabs, valname);
+                       ast_xml_free_attr(valname);
+               }
+               tmptext = ast_xml_get_text(tmp);
+               /* Check inside this node for any explanation about its meaning. */
+               if (tmptext) {
+                       /* Cleanup text. */
+                       xmldoc_string_cleanup(tmptext, &cleanstr, 1);
+                       ast_xml_free_text(tmptext);
+                       if (cleanstr && cleanstr->used > 0) {
+                               ast_str_append(buffer, 0, ":%s", cleanstr->str);
+                       }
+                       ast_free(cleanstr);
+               }
+               ast_str_append(buffer, 0, "\n");
+       }
+
+       return ret;
+}
+
+/*! \internal
+ *  \brief Parse a <variablelist> node and put all the output inside 'buffer'.
+ *  \param node The variablelist node pointer.
+ *  \param tabs A string to be appended at the begining of the output that will be stored
+ *         in buffer.
+ *  \param buffer This must be an already created ast_str. It will be used
+ *         to store the result (if already has something it will be appended to the current
+ *         string).
+ *  \retval 1 If a <variablelist> element is parsed.
+ *  \retval 0 On error.
+ */
+static int xmldoc_parse_variablelist(struct ast_xml_node *node, const char *tabs, struct ast_str **buffer)
+{
+       struct ast_xml_node *tmp;
+       const char *varname;
+       char *vartabs;
+       int ret = 0;
+
+       if (!node || !ast_xml_node_get_children(node)) {
+               return ret;
+       }
+
+       if (strcasecmp(ast_xml_node_get_name(node), "variablelist")) {
+               return ret;
+       }
+
+       /* use this spacing (add 4 spaces) inside a variablelist node. */
+       ast_asprintf(&vartabs, "%s    ", tabs);
+       if (!vartabs) {
+               return ret;
+       }
+       for (tmp = ast_xml_node_get_children(node); tmp; tmp = ast_xml_node_get_next(tmp)) {
+               /* We can have a <para> element inside the variable list */
+               if ((xmldoc_parse_para(tmp, (ret ? tabs : ""), "\n", buffer))) {
+                       ret = 1;
+                       continue;
+               } else if ((xmldoc_parse_specialtags(tmp, (ret ? tabs : ""), "\n", buffer))) {
+                       ret = 1;
+                       continue;
+               }
+
+               if (!strcasecmp(ast_xml_node_get_name(tmp), "variable")) {
+                       /* Store the variable name in buffer. */
+                       varname = ast_xml_get_attribute(tmp, "name");
+                       if (varname) {
+                               ast_str_append(buffer, 0, "%s<variable>%s</variable>: ", tabs, varname);
+                               ast_xml_free_attr(varname);
+                               /* Parse the <variable> possible values. */
+                               xmldoc_parse_variable(tmp, vartabs, buffer);
+                               ret = 1;
+                       }
+               }
+       }
+
+       ast_free(vartabs);
+
+       return ret;
+}
+
+/*! \internal
+ *  \brief Parse the <see-also> node content.
+ *  \param type 'application' or 'function'.
+ *  \param name Application or functions name.
+ *  \retval NULL on error.
+ *  \retval Content of the see-also node.
+ */
+static char *xmldoc_build_seealso(const char *type, const char *name)
+{
+       struct ast_str *outputstr;
+       char *output;
+       struct ast_xml_node *node;
+       const char *typename;
+       const char *content;
+
+       if (ast_strlen_zero(type) || ast_strlen_zero(name)) {
+               return NULL;
+       }
+
+       /* get the application/function root node. */
+       node = xmldoc_get_node(type, name, documentation_language);
+       if (!node || !ast_xml_node_get_children(node)) {
+               return NULL;
+       }
+
+       /* Find the <see-also> node. */
+       for (node = ast_xml_node_get_children(node); node; node = ast_xml_node_get_next(node)) {
+               if (!strcasecmp(ast_xml_node_get_name(node), "see-also")) {
+                       break;
+               }
+       }
+
+       if (!node || !ast_xml_node_get_children(node)) {
+               /* we couldnt find a <see-also> node. */
+               return NULL;
+       }
+
+       /* prepare the output string. */
+       outputstr = ast_str_create(128);
+       if (!outputstr) {
+               return NULL;
+       }
+
+       /* get into the <see-also> node. */
+       for (node = ast_xml_node_get_children(node); node; node = ast_xml_node_get_next(node)) {
+               if (strcasecmp(ast_xml_node_get_name(node), "ref")) {
+                       continue;
+               }
+
+               /* parse the <ref> node. 'type' attribute is required. */
+               typename = ast_xml_get_attribute(node, "type");
+               if (!typename) {
+                       continue;
+               }
+               content = ast_xml_get_text(node);
+               if (!content) {
+                       ast_xml_free_attr(typename);
+                       continue;
+               }
+               if (!strcasecmp(typename, "application") || !strcasecmp(typename, "function")) {
+                       ast_str_append(&outputstr, 0, "%s: Type <astcli>core show %s %s</astcli> for more info.\n",
+                               content, typename, content);
+               } else if (!strcasecmp(typename, "astcli")) {
+                       ast_str_append(&outputstr, 0, "%s: Type <astcli>help %s</astcli> for more info.\n", content, content);
+               } else if (!strcasecmp(typename, "link")) {
+                       ast_str_append(&outputstr, 0, "%s\n", content);
+               } else if (!strcasecmp(typename, "manpage")) {
+                       ast_str_append(&outputstr, 0, "ManPage: %s\n", content);
+               }
+               ast_xml_free_text(content);
+       }
+
+       output = ast_strdup(outputstr->str);
+       ast_free(outputstr);
+
+       return output;
+}
+
+/*! \internal
+ *  \brief Parse a <enum> node.
+ *  \brief fixnode An ast_xml_node pointer to the <enum> node.
+ *  \bried buffer The output buffer.
+ *  \retval 0 if content is not found inside the enum element (data is not appended to buffer).
+ *  \retval 1 if content is found and data is appended to buffer.
+ */
+static int xmldoc_parse_enum(struct ast_xml_node *fixnode, const char *tabs, struct ast_str **buffer)
+{
+       struct ast_xml_node *node = fixnode;
+       int ret = 0;
+
+       for (node = ast_xml_node_get_children(node); node; node = ast_xml_node_get_next(node)) {
+               if ((xmldoc_parse_para(node, (ret ? tabs : " - "), "\n", buffer))) {
+                       ret = 1;
+               } else if ((xmldoc_parse_specialtags(node, (ret ? tabs : " - "), "\n", buffer))) {
+                       ret = 1;
+               }
+       }
+       return ret;
+}
+
+/*! \internal
+ *  \brief Parse a <enumlist> node.
+ *  \param fixnode As ast_xml pointer to the <enumlist> node.
+ *  \param buffer The ast_str output buffer.
+ *  \retval 0 if no <enumlist> node was parsed.
+ *  \retval 1 if a <enumlist> node was parsed.
+ */
+static int xmldoc_parse_enumlist(struct ast_xml_node *fixnode, const char *tabs, struct ast_str **buffer)
+{
+       struct ast_xml_node *node = fixnode;
+       const char *enumname;
+       int ret = 0;
+
+       for (node = ast_xml_node_get_children(node); node; node = ast_xml_node_get_next(node)) {
+               if (strcasecmp(ast_xml_node_get_name(node), "enum")) {
+                       continue;
+               }
+
+               enumname = ast_xml_get_attribute(node, "name");
+               if (enumname) {
+                       ast_str_append(buffer, 0, "%s<enum>%s</enum>", tabs, enumname);
+                       ast_xml_free_attr(enumname);
+
+                       /* parse only enum elements inside a enumlist node. */
+                       if ((xmldoc_parse_enum(node, tabs, buffer))) {
+                               ret = 1;
+                       } else {
+                               ast_str_append(buffer, 0, "\n");
+                       }
+               }
+       }
+       return ret;
+}
+
+/*! \internal
+ *  \brief Parse an <option> node.
+ *  \param fixnode An ast_xml pointer to the <option> node.
+ *  \param tabs A string to be appended at the begining of each line being added to the
+ *              buffer string.
+ *  \param buffer The output buffer.
+ *  \retval 0 if no option node is parsed.
+ *  \retval 1 if an option node is parsed.
+ */
+static int xmldoc_parse_option(struct ast_xml_node *fixnode, const char *tabs, struct ast_str **buffer)
+{
+       struct ast_xml_node *node;
+       int ret = 0;
+       char *optiontabs;
+
+       ast_asprintf(&optiontabs, "%s    ", tabs);
+       if (!optiontabs) {
+               return ret;
+       }
+       for (node = ast_xml_node_get_children(fixnode); node; node = ast_xml_node_get_next(node)) {
+               if (!strcasecmp(ast_xml_node_get_name(node), "argument")) {
+                       /* if this is the first data appended to buffer, print a \n*/
+                       if (!ret && ast_xml_node_get_children(node)) {
+                               /* print \n */
+                               ast_str_append(buffer, 0, "\n");
+                       }
+                       if (xmldoc_parse_argument(node, 0, NULL, optiontabs, buffer)) {
+                               ret = 1;
+                       }
+                       continue;
+               }
+
+               if (xmldoc_parse_para(node, (ret ? tabs :  ""), "\n", buffer)) {
+                       ret = 1;
+               } else if (xmldoc_parse_specialtags(node, (ret ? tabs :  ""), "\n", buffer)) {
+                       ret = 1;
+               }
+
+               xmldoc_parse_variablelist(node, optiontabs, buffer);
+
+               xmldoc_parse_enumlist(node, optiontabs, buffer);
+       }
+       ast_free(optiontabs);
+
+       return ret;
+}
+
+/*! \internal
+ *  \brief Parse an <optionlist> element from the xml documentation.
+ *  \param fixnode Pointer to the optionlist xml node.
+ *  \param tabs A string to be appended at the begining of each line being added to the
+ *              buffer string.
+ *  \param buffer Output buffer to put what is inside the optionlist tag.
+ */
+static void xmldoc_parse_optionlist(struct ast_xml_node *fixnode, const char *tabs, struct ast_str **buffer)
+{
+       struct ast_xml_node *node;
+       const char *optname;
+       char *optionsyntax;
+
+       for (node = ast_xml_node_get_children(fixnode); node; node = ast_xml_node_get_next(node)) {
+               /* Start appending every option tag. */
+               if (strcasecmp(ast_xml_node_get_name(node), "option")) {
+                       continue;
+               }
+
+               /* Get the option name. */
+               optname = ast_xml_get_attribute(node, "name");
+               if (!optname) {
+                       continue;
+               }
+
+               optionsyntax = xmldoc_get_syntax(node, optname, "argument", 0, 1);
+               if (!optionsyntax) {
+                       continue;
+               }
+
+               ast_str_append(buffer, 0, "%s%s: ", tabs, optionsyntax);
+
+               if (!xmldoc_parse_option(node, tabs, buffer)) {
+                       ast_str_append(buffer, 0, "\n");
+               }
+       }
 }
 
-static int acf_exception_read(struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
+/*! \internal
+ *  \brief Parse a 'parameter' tag inside a syntax element.
+ *  \param fixnode A pointer to the 'parameter' xml node.
+ *  \param tabs A string to be appended at the beginning of each line being printed inside
+ *              'buffer'.
+ *  \param buffer String buffer to put values found inside the parameter element.
+ */
+static void xmldoc_parse_parameter(struct ast_xml_node *fixnode, const char *tabs, struct ast_str **buffer)
 {
-       struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
-       struct pbx_exception *exception = NULL;
-       if (!ds || !ds->data)
-               return -1;
-       exception = ds->data;
-       if (!strcasecmp(data, "REASON"))
-               ast_copy_string(buf, exception->reason, buflen);
-       else if (!strcasecmp(data, "CONTEXT"))
-               ast_copy_string(buf, exception->context, buflen);
-       else if (!strncasecmp(data, "EXTEN", 5))
-               ast_copy_string(buf, exception->exten, buflen);
-       else if (!strcasecmp(data, "PRIORITY"))
-               snprintf(buf, buflen, "%d", exception->priority);
-       else
-               return -1;
-       return 0;
-}
+       const char *paramname;
+       struct ast_xml_node *node = fixnode;
+       int hasarguments, printed = 0;
+       char *internaltabs;
 
-static struct ast_custom_function exception_function = {
-       .name = "EXCEPTION",
-       .synopsis = "Retrieve the details of the current dialplan exception",
-       .desc =
-"The following fields are available for retrieval:\n"
-"  reason    INVALID, ERROR, RESPONSETIMEOUT, ABSOLUTETIMEOUT, or custom\n"
-"               value set by the RaiseException() application\n"
-"  context   The context executing when the exception occurred\n"
-"  exten     The extension executing when the exception occurred\n"
-"  priority  The numeric priority executing when the exception occurred\n",
-       .syntax = "EXCEPTION(<field>)",
-       .read = acf_exception_read,
-};
+       if (strcasecmp(ast_xml_node_get_name(node), "parameter")) {
+               return;
+       }
 
-static char *handle_show_functions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+       hasarguments = xmldoc_has_arguments(node);
+       if (!(paramname = ast_xml_get_attribute(node, "name"))) {
+               /* parameter MUST have an attribute name. */
+               return;
+       }
+
+       ast_asprintf(&internaltabs, "%s    ", tabs);
+       if (!internaltabs) {
+               return;
+       }
+
+       if (!hasarguments) {
+               ast_str_append(buffer, 0, "%s\n", paramname);
+               ast_xml_free_attr(paramname);
+               printed = 1;
+       }
+
+       for (node = ast_xml_node_get_children(node); node; node = ast_xml_node_get_next(node)) {
+               if (!strcasecmp(ast_xml_node_get_name(node), "optionlist")) {
+                       xmldoc_parse_optionlist(node, internaltabs, buffer);
+               } else if (!strcasecmp(ast_xml_node_get_name(node), "enumlist")) {
+                       xmldoc_parse_enumlist(node, internaltabs, buffer);
+               } else if (!strcasecmp(ast_xml_node_get_name(node), "argument")) {
+                       xmldoc_parse_argument(node, 1, internaltabs, (!hasarguments ? "        " : ""), buffer);
+               } else if (!strcasecmp(ast_xml_node_get_name(node), "para")) {
+                       if (!printed) {
+                               ast_str_append(buffer, 0, "%s\n", paramname);
+                               ast_xml_free_attr(paramname);
+                               printed = 1;
+                       }
+                       xmldoc_parse_para(node, internaltabs, "\n", buffer);
+                       continue;
+               } else if ((xmldoc_parse_specialtags(node, internaltabs, "\n", buffer))) {
+                       continue;
+               }
+       }
+       ast_free(internaltabs);
+}
+
+/*! \internal
+ *  \brief Generate the [arguments] tag based on type of node 'application' or
+ *         'function' and name.
+ *  \param type 'application' or 'function' ?
+ *  \param name Name of the application or function to build the 'arguments' tag.
+ *  \retval NULL on error.
+ *  \retval Output buffer with the [arguments] tag content.
+ */
+static char *xmldoc_build_arguments(const char *type, const char *name)
 {
-       struct ast_custom_function *acf;
-       int count_acf = 0;
-       int like = 0;
+       struct ast_xml_node *node;
+       struct ast_str *ret = ast_str_create(128);
+       char *retstr = NULL;
 
-       switch (cmd) {
-       case CLI_INIT:
-               e->command = "core show functions [like]";
-               e->usage = 
-                       "Usage: core show functions [like <text>]\n"
-                       "       List builtin functions, optionally only those matching a given string\n";
+       if (ast_strlen_zero(type) || ast_strlen_zero(name)) {
                return NULL;
-       case CLI_GENERATE:
+       }
+
+       node = xmldoc_get_node(type, name, documentation_language);
+
+       if (!node || !ast_xml_node_get_children(node)) {
                return NULL;
        }
 
-       if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) {
-               like = 1;
-       } else if (a->argc != 3) {
-               return CLI_SHOWUSAGE;
+       /* Find the syntax field. */
+       for (node = ast_xml_node_get_children(node); node; node = ast_xml_node_get_next(node)) {
+               if (!strcasecmp(ast_xml_node_get_name(node), "syntax")) {
+                       break;
+               }
        }
 
-       ast_cli(a->fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed");
+       if (!node || !ast_xml_node_get_children(node)) {
+               /* We couldn't find the syntax node. */
+               return NULL;
+       }
 
-       AST_RWLIST_RDLOCK(&acf_root);
-       AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
-               if (!like || strstr(acf->name, a->argv[4])) {
-                       count_acf++;
-                       ast_cli(a->fd, "%-20.20s  %-35.35s  %s\n", acf->name, acf->syntax, acf->synopsis);
-               }
+       for (node = ast_xml_node_get_children(node); node; node = ast_xml_node_get_next(node)) {
+               xmldoc_parse_parameter(node, "", &ret);
        }
-       AST_RWLIST_UNLOCK(&acf_root);
 
-       ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : "");
+       if (ret->used > 0) {
+               /* remove last '\n' */
+               if (ret->str[ret->used - 1] == '\n') {
+                       ret->str[ret->used - 1] = '\0';
+                       ret->used--;
+               }
+               retstr = ast_strdup(ret->str);
+       }
+       ast_free(ret);
 
-       return CLI_SUCCESS;
+       return retstr;
 }
 
-static char *handle_show_function(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+/*! \internal
+ *  \brief Return the string within a node formatted with <para> and <variablelist> elements.
+ *  \param node Parent node where content resides.
+ *  \param raw If set, return the node's content without further processing.
+ *  \param raw_wrap Wrap raw text.
+ *  \retval NULL on error
+ *  \retval Node content on success.
+ */
+static struct ast_str *xmldoc_get_formatted(struct ast_xml_node *node, int raw_output, int raw_wrap)
 {
-       struct ast_custom_function *acf;
-       /* Maximum number of characters added by terminal coloring is 22 */
-       char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
-       char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
-       char stxtitle[40], *syntax = NULL;
-       int synopsis_size, description_size, syntax_size;
-       char *ret = NULL;
-       int which = 0;
-       int wordlen;
+       struct ast_xml_node *tmp;
+       const char *notcleanret, *tmpstr;
+       struct ast_str *ret = ast_str_create(128);
 
-       switch (cmd) {
-       case CLI_INIT:
-               e->command = "core show function";
-               e->usage = 
-                       "Usage: core show function <function>\n"
-                       "       Describe a particular dialplan function.\n";
-               return NULL;
-       case CLI_GENERATE:      
-               wordlen = strlen(a->word);
-               /* case-insensitive for convenience in this 'complete' function */
-               AST_RWLIST_RDLOCK(&acf_root);
-               AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
-                       if (!strncasecmp(a->word, acf->name, wordlen) && ++which > a->n) {
-                               ret = ast_strdup(acf->name);
-                               break;
+       if (raw_output) {
+               notcleanret = ast_xml_get_text(node);
+               tmpstr = notcleanret;
+               xmldoc_string_cleanup(ast_skip_blanks(notcleanret), &ret, 0);
+               ast_xml_free_text(tmpstr);
+       } else {
+               for (tmp = ast_xml_node_get_children(node); tmp; tmp = ast_xml_node_get_next(tmp)) {
+                       /* if found, parse a <para> element. */
+                       if (xmldoc_parse_para(tmp, "", "\n", &ret)) {
+                               continue;
+                       } else if (xmldoc_parse_specialtags(tmp, "", "\n", &ret)) {
+                               continue;
                        }
+                       /* if found, parse a <variablelist> element. */
+                       xmldoc_parse_variablelist(tmp, "", &ret);
+                       xmldoc_parse_enumlist(tmp, "    ", &ret);
                }
-               AST_RWLIST_UNLOCK(&acf_root);
+               /* remove last '\n' */
+               /* XXX Don't modify ast_str internals manually */
+               if (ret->str[ret->used-1] == '\n') {
+                       ret->str[ret->used-1] = '\0';
+                       ret->used--;
+               }
+       }
+       return ret;
+}
+
+/*! \internal
+ *  \brief Get the content of a field (synopsis, description, etc) from an asterisk document tree
+ *  \param type Type of element (application, function, ...).
+ *  \param name Name of element (Dial, Echo, Playback, ...).
+ *  \param var Name of field to return (synopsis, description, etc).
+ *  \param raw Field only contains text, no other elements inside it.
+ *  \retval NULL On error.
+ *  \retval Field text content on success.
+ */
+static char *xmldoc_build_field(const char *type, const char *name, const char *var, int raw)
+{
+       struct ast_xml_node *node;
+       char *ret = NULL;
+       struct ast_str *formatted;
 
+       if (ast_strlen_zero(type) || ast_strlen_zero(name)) {
+               ast_log(LOG_ERROR, "Tried to look in XML tree with faulty values.\n");
                return ret;
        }
 
-       if (a->argc < 4)
-               return CLI_SHOWUSAGE;
-
-       if (!(acf = ast_custom_function_find(a->argv[3]))) {
-               ast_cli(a->fd, "No function by that name registered.\n");
-               return CLI_FAILURE;
+       node = xmldoc_get_node(type, name, documentation_language);
 
+       if (!node) {
+               ast_log(LOG_WARNING, "Counldn't find %s %s in XML documentation\n", type, name);
+               return ret;
        }
 
-       if (acf->synopsis)
-               synopsis_size = strlen(acf->synopsis) + 23;
-       else
-               synopsis_size = strlen("Not available") + 23;
-       synopsis = alloca(synopsis_size);
-
-       if (acf->desc)
-               description_size = strlen(acf->desc) + 23;
-       else
-               description_size = strlen("Not available") + 23;
-       description = alloca(description_size);
+       node = ast_xml_find_element(ast_xml_node_get_children(node), var, NULL, NULL);
 
-       if (acf->syntax)
-               syntax_size = strlen(acf->syntax) + 23;
-       else
-               syntax_size = strlen("Not available") + 23;
-       syntax = alloca(syntax_size);
+       if (!node || !ast_xml_node_get_children(node)) {
+               ast_log(LOG_DEBUG, "Cannot find variable '%s' in tree '%s'\n", name, var);
+               return ret;
+       }
 
-       snprintf(info, 64 + AST_MAX_APP, "\n  -= Info about function '%s' =- \n\n", acf->name);
-       term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
-       term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
-       term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
-       term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
-       term_color(syntax,
-                  acf->syntax ? acf->syntax : "Not available",
-                  COLOR_CYAN, 0, syntax_size);
-       term_color(synopsis,
-                  acf->synopsis ? acf->synopsis : "Not available",
-                  COLOR_CYAN, 0, synopsis_size);
-       term_color(description,
-                  acf->desc ? acf->desc : "Not available",
-                  COLOR_CYAN, 0, description_size);
-
-       ast_cli(a->fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description);
+       formatted = xmldoc_get_formatted(node, raw, raw);
+       if (formatted->used > 0) {
+               ret = ast_strdup(formatted->str);
+       }
+       ast_free(formatted);
 
-       return CLI_SUCCESS;
+       return ret;
 }
+#endif /* AST_XML_DOCS */
 
-struct ast_custom_function *ast_custom_function_find(const char *name)
+/*! \internal
+ *  \brief Retrieve the XML documentation of a specified ast_custom_function,
+ *         and populate ast_custom_function string fields.
+ *  \param acf ast_custom_function structure with empty 'desc' and 'synopsis'
+ *             but with a function 'name'.
+ *  \retval -1 On error.
+ *  \retval 0 On succes.
+ */
+static int acf_retrieve_docs(struct ast_custom_function *acf)
 {
-       struct ast_custom_function *acf = NULL;
+#ifdef AST_XML_DOCS
+       char *tmpxml;
 
-       AST_RWLIST_RDLOCK(&acf_root);
-       AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
-               if (!strcmp(name, acf->name))
-                       break;
+       /* Let's try to find it in the Documentation XML */
+       if (!ast_strlen_zero(acf->desc) || !ast_strlen_zero(acf->synopsis)) {
+               return 0;
        }
-       AST_RWLIST_UNLOCK(&acf_root);
 
-       return acf;
-}
+       if (ast_string_field_init(acf, 128)) {
+               return -1;
+       }
 
-int ast_custom_function_unregister(struct ast_custom_function *acf)
-{
-       struct ast_custom_function *cur;
+       /* load synopsis */
+       tmpxml = xmldoc_build_field("function", acf->name, "synopsis", 1);
+       ast_string_field_set(acf, synopsis, tmpxml);
+       ast_free(tmpxml);
 
-       if (!acf)
-               return -1;
+       /* load description */
+       tmpxml = xmldoc_build_field("function", acf->name, "description", 0);
+       ast_string_field_set(acf, desc, tmpxml);
+       ast_free(tmpxml);
 
-       AST_RWLIST_WRLOCK(&acf_root);
-       if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist)))
-               ast_verb(2, "Unregistered custom function %s\n", cur->name);
-       AST_RWLIST_UNLOCK(&acf_root);
+       /* load syntax */
+       tmpxml = xmldoc_build_syntax("function", acf->name);
+       ast_string_field_set(acf, syntax, tmpxml);
+       ast_free(tmpxml);
 
-       return cur ? 0 : -1;
+       /* load arguments */
+       tmpxml = xmldoc_build_arguments("function", acf->name);
+       ast_string_field_set(acf, arguments, tmpxml);
+       ast_free(tmpxml);
+
+       /* load seealso */
+       tmpxml = xmldoc_build_seealso("function", acf->name);
+       ast_string_field_set(acf, seealso, tmpxml);
+       ast_free(tmpxml);
+
+       acf->docsrc = AST_XML_DOC;
+#endif
+
+       return 0;
 }
 
 int __ast_custom_function_register(struct ast_custom_function *acf, struct ast_module *mod)
@@ -2784,10 +4627,16 @@ int __ast_custom_function_register(struct ast_custom_function *acf, struct ast_m
        struct ast_custom_function *cur;
        char tmps[80];
 
-       if (!acf)
+       if (!acf) {
                return -1;
+       }
 
        acf->mod = mod;
+       acf->docsrc = AST_STATIC_DOC;
+
+       if (acf_retrieve_docs(acf)) {
+               return -1;
+       }
 
        AST_RWLIST_WRLOCK(&acf_root);
 
@@ -2807,8 +4656,10 @@ int __ast_custom_function_register(struct ast_custom_function *acf, struct ast_m
                }
        }
        AST_RWLIST_TRAVERSE_SAFE_END;
-       if (!cur)
+
+       if (!cur) {
                AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist);
+       }
 
        AST_RWLIST_UNLOCK(&acf_root);
 
@@ -4478,6 +6329,9 @@ int ast_register_application2(const char *app, int (*execute)(struct ast_channel
        struct ast_app *tmp, *cur = NULL;
        char tmps[80];
        int length, res;
+#ifdef AST_XML_DOCS
+       char *tmpxml;
+#endif
 
        AST_RWLIST_WRLOCK(&apps);
        AST_RWLIST_TRAVERSE(&apps, tmp, list) {
@@ -4496,10 +6350,50 @@ int ast_register_application2(const char *app, int (*execute)(struct ast_channel
                return -1;
        }
 
+       if (ast_string_field_init(tmp, 128)) {
+               ast_free(tmp);
+               return -1;
+       }
+
+#ifdef AST_XML_DOCS
+       /* Try to lookup the docs in our XML documentation database */
+       if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) {
+               /* load synopsis */
+               tmpxml = xmldoc_build_field("application", app, "synopsis", 1);
+               ast_string_field_set(tmp, synopsis, tmpxml);
+               ast_free(tmpxml);
+
+               /* load description */
+               tmpxml = xmldoc_build_field("application", app, "description", 0);
+               ast_string_field_set(tmp, description, tmpxml);
+               ast_free(tmpxml);
+
+               /* load syntax */
+               tmpxml = xmldoc_build_syntax("application", app);
+               ast_string_field_set(tmp, syntax, tmpxml);
+               ast_free(tmpxml);
+
+               /* load arguments */
+               tmpxml = xmldoc_build_arguments("application", app);
+               ast_string_field_set(tmp, arguments, tmpxml);
+               ast_free(tmpxml);
+
+               /* load seealso */
+               tmpxml = xmldoc_build_seealso("application", app);
+               ast_string_field_set(tmp, seealso, tmpxml);
+               ast_free(tmpxml);
+               tmp->docsrc = AST_XML_DOC;
+       } else {
+#endif
+               ast_string_field_set(tmp, synopsis, synopsis);
+               ast_string_field_set(tmp, description, description);
+               tmp->docsrc = AST_STATIC_DOC;
+#ifdef AST_XML_DOCS
+       }
+#endif
+
        strcpy(tmp->name, app);
        tmp->execute = execute;
-       tmp->synopsis = synopsis;
-       tmp->description = description;
        tmp->module = mod;
 
        /* Store in alphabetical order */
@@ -4520,6 +6414,123 @@ int ast_register_application2(const char *app, int (*execute)(struct ast_channel
        return 0;
 }
 
+#ifdef AST_XML_DOCS
+/*! \brief Close and unload XML documentation. */
+static void xmldoc_unload_documentation(void)
+{
+        struct documentation_tree *doctree;
+
+       AST_RWLIST_WRLOCK(&xmldoc_tree);
+       while ((doctree = AST_RWLIST_REMOVE_HEAD(&xmldoc_tree, entry))) {
+               ast_free(doctree->filename);
+               ast_xml_close(doctree->doc);
+       }
+       AST_RWLIST_UNLOCK(&xmldoc_tree);
+
+       ast_xml_finish();
+}
+
+int ast_load_documentation(void)
+{
+       struct ast_xml_node *root_node;
+       struct ast_xml_doc *tmpdoc;
+       struct documentation_tree *doc_tree;
+       char *xmlpattern;
+       struct ast_config *cfg = NULL;
+       struct ast_variable *var = NULL;
+       struct ast_flags cnfflags = { 0 };
+       int globret, i, dup, duplicate;
+       glob_t globbuf;
+
+       /* setup default XML documentation language */
+       snprintf(documentation_language, sizeof(documentation_language), default_documentation_language);
+
+       if (!(cfg = ast_config_load2("asterisk.conf", "" /* core can't reload */, cnfflags))) {
+               ast_log(LOG_ERROR, "No asterisk.conf? That cannot be good.\n");
+       }
+
+       for (var = ast_variable_browse(cfg, "options"); var; var = var->next) {
+               if (!strcasecmp(var->name, "documentation_language")) {
+                       if (!ast_strlen_zero(var->value)) {
+                               snprintf(documentation_language, sizeof(documentation_language), "%s", var->value);
+                       }
+               }
+       }
+        ast_config_destroy(cfg);
+
+       /* initialize the XML library. */
+       ast_xml_init();
+
+       /* register function to be run when asterisk finish. */
+       ast_register_atexit(xmldoc_unload_documentation);
+
+       /* Get every *-LANG.xml file inside $(ASTDATADIR)/documentation */
+       ast_asprintf(&xmlpattern, "%s/documentation{/thirdparty/,/}*-{%s,%.2s_??,%s}.xml", ast_config_AST_DATA_DIR,
+                       documentation_language, documentation_language, default_documentation_language);
+       globbuf.gl_offs = 0;    /* initialize it to silence gcc */
+       globret = glob(xmlpattern, MY_GLOB_FLAGS | GLOB_BRACE, NULL, &globbuf);
+       if (globret == GLOB_NOSPACE) {
+               ast_log(LOG_WARNING, "Glob Expansion of pattern '%s' failed: Not enough memory\n", xmlpattern);
+               ast_free(xmlpattern);
+               return 1;
+       } else if (globret  == GLOB_ABORTED) {
+               ast_log(LOG_WARNING, "Glob Expansion of pattern '%s' failed: Read error\n", xmlpattern);
+               ast_free(xmlpattern);
+               return 1;
+       }
+       ast_free(xmlpattern);
+
+       AST_RWLIST_WRLOCK(&xmldoc_tree);
+       /* loop over expanded files */
+       for (i = 0; i < globbuf.gl_pathc; i++) {
+               /* check for duplicates (if we already [try to] open the same file. */
+               duplicate = 0;
+               for (dup = 0; dup < i; dup++) {
+                       if (!strcmp(globbuf.gl_pathv[i], globbuf.gl_pathv[dup])) {
+                               duplicate = 1;
+                               break;
+                       }
+               }
+               if (duplicate) {
+                       continue;
+               }
+               tmpdoc = NULL;
+               tmpdoc = ast_xml_open(globbuf.gl_pathv[i]);
+               if (!tmpdoc) {
+                       ast_log(LOG_ERROR, "Could not open XML documentation at '%s'\n", globbuf.gl_pathv[i]);
+                       continue;
+               }
+               /* Get doc root node and check if it starts with '<docs>' */
+               root_node = ast_xml_get_root(tmpdoc);
+               if (!root_node) {
+                       ast_log(LOG_ERROR, "Error getting documentation root node");
+                       ast_xml_close(tmpdoc);
+                       continue;
+               }
+               /* Check root node name for malformed xmls. */
+               if (strcmp(ast_xml_node_get_name(root_node), "docs")) {
+                       ast_log(LOG_ERROR, "Documentation file is not well formed!\n");
+                       ast_xml_close(tmpdoc);
+                       continue;
+               }
+               doc_tree = ast_calloc(1, sizeof(*doc_tree));
+               if (!doc_tree) {
+                       ast_log(LOG_ERROR, "Unable to allocate documentation_tree structure!\n");
+                       ast_xml_close(tmpdoc);
+                       continue;
+               }
+               doc_tree->doc = tmpdoc;
+               doc_tree->filename = ast_strdup(globbuf.gl_pathv[i]);
+               AST_RWLIST_INSERT_TAIL(&xmldoc_tree, doc_tree, entry);
+       }
+       AST_RWLIST_UNLOCK(&xmldoc_tree);
+
+       globfree(&globbuf);
+
+       return 0;
+}
+#endif /* AST_XML_DOCS */
+
 /*
  * Append to the list. We don't have a tail pointer because we need
  * to scan the list anyways to check for duplicates during insertion.
@@ -4553,6 +6564,78 @@ void ast_unregister_switch(struct ast_switch *sw)
  * Help for CLI commands ...
  */
 
+static void print_app_docs(struct ast_app *aa, int fd)
+{
+       /* Maximum number of characters added by terminal coloring is 22 */
+       char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], stxtitle[40], argtitle[40];
+       char seealsotitle[40];
+       char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *syntax = NULL, *arguments = NULL;
+       char *seealso = NULL;
+       int syntax_size, synopsis_size, description_size, arguments_size, seealso_size;
+
+       snprintf(info, sizeof(info), "\n  -= Info about application '%s' =- \n\n", aa->name);
+       term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle));
+
+       term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
+       term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
+       term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
+       term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
+       term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40);
+
+#ifdef AST_XML_DOCS
+       if (aa->docsrc == AST_XML_DOC) {
+               description = xmldoc_colorization(S_OR(aa->description, "Not available"));
+               arguments = xmldoc_colorization(S_OR(aa->arguments, "Not available"));
+               synopsis = xmldoc_colorization(S_OR(aa->synopsis, "Not available"));
+               seealso = xmldoc_colorization(S_OR(aa->seealso, "Not available"));
+               
+               if (!synopsis || !description || !arguments || !seealso) {
+                       goto return_cleanup;
+               }
+       } else 
+#endif
+       {
+               synopsis_size = strlen(S_OR(aa->synopsis, "Not Available")) + MAX_ESCAPE_CHARS;
+               synopsis = ast_malloc(synopsis_size);
+
+               description_size = strlen(S_OR(aa->description, "Not Available")) + MAX_ESCAPE_CHARS;
+               description = ast_malloc(description_size);
+
+               arguments_size = strlen(S_OR(aa->arguments, "Not Available")) + MAX_ESCAPE_CHARS;
+               arguments = ast_malloc(arguments_size);
+
+               seealso_size = strlen(S_OR(aa->seealso, "Not Available")) + MAX_ESCAPE_CHARS;
+               seealso = ast_malloc(seealso_size);
+
+               if (!synopsis || !description || !arguments || !seealso) {
+                       goto return_cleanup;
+               }
+
+               term_color(synopsis, S_OR(aa->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size);
+               term_color(description, S_OR(aa->description, "Not available"), COLOR_CYAN, 0, description_size);
+               term_color(arguments, S_OR(aa->arguments, "Not available"), COLOR_CYAN, 0, arguments_size);
+               term_color(seealso, S_OR(aa->seealso, "Not available"), COLOR_CYAN, 0, seealso_size);
+       }
+
+       /* Handle the syntax the same for both XML and raw docs */
+       syntax_size = strlen(S_OR(aa->syntax, "Not Available")) + MAX_ESCAPE_CHARS;
+       if (!(syntax = ast_malloc(syntax_size))) {
+               goto return_cleanup;
+       }
+       term_color(syntax, S_OR(aa->syntax, "Not available"), COLOR_CYAN, 0, syntax_size);
+
+       ast_cli(fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n", 
+                       infotitle, syntitle, synopsis, destitle, description, 
+                       stxtitle, syntax, argtitle, arguments, seealsotitle, seealso);
+
+return_cleanup:
+       ast_free(description);
+       ast_free(arguments);
+       ast_free(synopsis);
+       ast_free(seealso);
+       ast_free(syntax);
+}
+
 /*
  * \brief 'show application' CLI command implementation function...
  */
@@ -4591,58 +6674,22 @@ static char *handle_show_application(struct ast_cli_entry *e, int cmd, struct as
                return ret;
        }
 
-       if (a->argc < 4)
+       if (a->argc < 4) {
                return CLI_SHOWUSAGE;
+       }
 
-       /* ... go through all applications ... */
        AST_RWLIST_RDLOCK(&apps);
        AST_RWLIST_TRAVERSE(&apps, aa, list) {
-               /* ... compare this application name with all arguments given
-                * to 'show application' command ... */
+               /* Check for each app that was supplied as an argument */
                for (app = 3; app < a->argc; app++) {
-                       if (!strcasecmp(aa->name, a->argv[app])) {
-                               /* Maximum number of characters added by terminal coloring is 22 */
-                               char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
-                               char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
-                               int synopsis_size, description_size;
-
-                               no_registered_app = 0;
+                       if (strcasecmp(aa->name, a->argv[app])) {
+                               continue;
+                       }
 
-                               if (aa->synopsis)
-                                       synopsis_size = strlen(aa->synopsis) + 23;
-                               else
-                                       synopsis_size = strlen("Not available") + 23;
-                               synopsis = alloca(synopsis_size);
+                       /* We found it! */
+                       no_registered_app = 0;
 
-                               if (aa->description)
-                                       description_size = strlen(aa->description) + 23;
-                               else
-                                       description_size = strlen("Not available") + 23;
-                               description = alloca(description_size);
-
-                               if (synopsis && description) {
-                                       snprintf(info, 64 + AST_MAX_APP, "\n  -= Info about application '%s' =- \n\n", aa->name);
-                                       term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
-                                       term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
-                                       term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
-                                       term_color(synopsis,
-                                                                       aa->synopsis ? aa->synopsis : "Not available",
-                                                                       COLOR_CYAN, 0, synopsis_size);
-                                       term_color(description,
-                                                                       aa->description ? aa->description : "Not available",
-                                                                       COLOR_CYAN, 0, description_size);
-
-                                       ast_cli(a->fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description);
-                               } else {
-                                       /* ... one of our applications, show info ...*/
-                                       ast_cli(a->fd,"\n  -= Info about application '%s' =- \n\n"
-                                               "[Synopsis]\n  %s\n\n"
-                                               "[Description]\n%s\n",
-                                               aa->name,
-                                               aa->synopsis ? aa->synopsis : "Not available",
-                                               aa->description ? aa->description : "Not available");
-                               }
-                       }
+                       print_app_docs(aa, a->fd);
                }
        }
        AST_RWLIST_UNLOCK(&apps);
@@ -5744,6 +7791,11 @@ int ast_unregister_application(const char *app)
                        unreference_cached_app(tmp);
                        AST_RWLIST_REMOVE_CURRENT(list);
                        ast_verb(2, "Unregistered application '%s'\n", tmp->name);
+#ifdef AST_XML_DOCS
+                       if (tmp->docsrc == AST_XML_DOC) {
+                               ast_string_field_free_memory(tmp);
+                       }
+#endif
                        ast_free(tmp);
                        break;
                }
@@ -8534,12 +10586,12 @@ int load_pbx(void)
        /* Register builtin applications */
        for (x = 0; x < sizeof(builtins) / sizeof(struct pbx_builtin); x++) {
                ast_verb(1, "[%s]\n", builtins[x].name);
-               if (ast_register_application2(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description, NULL)) {
+               if (ast_register_application2(builtins[x].name, builtins[x].execute, NULL, NULL, NULL)) {
                        ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
                        return -1;
                }
        }
-       
+
        /* Register manager application */
        ast_manager_register2("ShowDialPlan", EVENT_FLAG_CONFIG | EVENT_FLAG_REPORTING, manager_show_dialplan, "List dialplan", mandescr_show_dialplan);
 
index d12135f24c7e6694260e3f7c398b03a414c27cd1..7f38ee5cec58034bcaf5052b2323ed2b006e6627 100644 (file)
@@ -199,32 +199,72 @@ char *term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int
        return outbuf;
 }
 
-char *term_color_code(char *outbuf, int fgcolor, int bgcolor, int maxout)
+static void check_fgcolor(int *fgcolor, int *attr)
 {
-       int attr = 0;
-       if ((!vt100compat) || (!fgcolor)) {
-               *outbuf = '\0';
-               return outbuf;
+       if (*fgcolor & 128) {
+               *attr = ast_opt_light_background ? 0 : ATTR_BRIGHT;
+               *fgcolor &= ~128;
+       }
+       
+       if (ast_opt_light_background) {
+               *fgcolor = opposite(*fgcolor);
        }
+}
 
-       if (fgcolor & 128) {
-               attr = ast_opt_light_background ? 0 : ATTR_BRIGHT;
-               fgcolor &= ~128;
+static void check_bgcolor(int *bgcolor)
+{
+       if (*bgcolor) {
+               *bgcolor &= ~128;
        }
+}
 
-       if (ast_opt_light_background) {
-               fgcolor = opposite(fgcolor);
+static int check_colors_allowed(int fgcolor)
+{
+       return (!vt100compat || !fgcolor) ? 0 : 1;
+}
+
+int ast_term_color_code(struct ast_str **str, int fgcolor, int bgcolor)
+{
+       int attr = 0;
+
+       if (!check_colors_allowed(fgcolor)) {
+               return -1;
        }
 
-       if (bgcolor) {
-               bgcolor &= ~128;
+       check_fgcolor(&fgcolor, &attr);
+       check_bgcolor(&bgcolor);
+       
+       if (ast_opt_force_black_background) {
+               ast_str_append(str, 0, "%c[%d;%d;%dm", ESC, attr, fgcolor, COLOR_BLACK + 10);
+       } else if (bgcolor) {
+               ast_str_append(str, 0, "%c[%d;%d;%dm", ESC, attr, fgcolor, bgcolor + 10);
+       } else {
+               ast_str_append(str, 0, "%c[%d;%dm", ESC, attr, fgcolor);
        }
 
+       return 0;
+}
+
+char *term_color_code(char *outbuf, int fgcolor, int bgcolor, int maxout)
+{
+       int attr = 0;
+
+       if (!check_colors_allowed(fgcolor)) {
+               *outbuf = '\0';
+               return outbuf;
+       }
+
+       check_fgcolor(&fgcolor, &attr);
+       check_bgcolor(&bgcolor);
+
        if (ast_opt_force_black_background) {
+               snprintf(outbuf, maxout, "%c[%d;%d;%dm", ESC, attr, fgcolor, COLOR_BLACK + 10);
+       } else if (bgcolor) {
                snprintf(outbuf, maxout, "%c[%d;%d;%dm", ESC, attr, fgcolor, bgcolor + 10);
        } else {
                snprintf(outbuf, maxout, "%c[%d;%dm", ESC, attr, fgcolor);
        }
+
        return outbuf;
 }
 
diff --git a/main/xml.c b/main/xml.c
new file mode 100644 (file)
index 0000000..9a0c66d
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2008, Eliel C. Sardanons (LU1ALY) <eliels@gmail.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief XML abstraction layer
+ *
+ * \author Eliel C. Sardanons (LU1ALY) <eliels@gmail.com>
+ */
+
+#include "asterisk.h"
+#include "asterisk/xml.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#if defined(HAVE_LIBXML2)
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+/* libxml2 ast_xml implementation. */
+
+
+int ast_xml_init(void)
+{
+       LIBXML_TEST_VERSION
+
+       return 0;
+}
+
+int ast_xml_finish(void)
+{
+       xmlCleanupParser();
+
+       return 0;
+}
+
+struct ast_xml_doc *ast_xml_open(char *filename)
+{
+       xmlDoc *doc;
+
+       if (!filename) {
+               return NULL;
+       }
+
+       doc = xmlReadFile(filename, NULL, XML_PARSE_RECOVER);
+
+       return (struct ast_xml_doc *) doc;
+}
+
+
+void ast_xml_close(struct ast_xml_doc *doc)
+{
+       if (!doc) {
+               return;
+       }
+
+       xmlFreeDoc((xmlDoc *) doc);
+       doc = NULL;
+}
+
+
+struct ast_xml_node *ast_xml_get_root(struct ast_xml_doc *doc)
+{
+       xmlNode *root_node;
+
+       if (!doc) {
+               return NULL;
+       }
+
+       root_node = xmlDocGetRootElement((xmlDoc *) doc);
+
+       return (struct ast_xml_node *) root_node;
+}
+
+void ast_xml_free_node(struct ast_xml_node *node)
+{
+       if (!node) {
+               return;
+       }
+
+       xmlFreeNode((xmlNode *) node);
+       node = NULL;
+}
+
+void ast_xml_free_attr(const char *attribute)
+{
+       if (attribute) {
+               xmlFree((char *) attribute);
+       }
+}
+
+void ast_xml_free_text(const char *text)
+{
+       if (text) {
+               xmlFree((char *) text);
+       }
+}
+
+const char *ast_xml_get_attribute(struct ast_xml_node *node, const char *attrname)
+{
+       xmlChar *attrvalue;
+
+       if (!node) {
+               return NULL;
+       }
+
+       if (!attrname) {
+               return NULL;
+       }
+
+       attrvalue = xmlGetProp((xmlNode *) node, (xmlChar *) attrname);
+
+       return (const char *) attrvalue;
+}
+
+struct ast_xml_node *ast_xml_find_element(struct ast_xml_node *root_node, const char *name, const char *attrname, const char *attrvalue)
+{
+       struct ast_xml_node *cur;
+       const char *attr;
+
+       if (!root_node) {
+               return NULL;
+       }
+
+       for (cur = root_node; cur; cur = ast_xml_node_get_next(cur)) {
+               /* Check if the name matchs */
+               if (strcmp(ast_xml_node_get_name(cur), name)) {
+                       continue;
+               }
+               /* We need to check for a specific attribute name? */
+               if (!attrname || !attrvalue) {
+                       return cur;
+               }
+               /* Get the attribute, we need to compare it. */
+               if ((attr = ast_xml_get_attribute(cur, attrname))) {
+                       /* does attribute name/value matches? */
+                       if (!strcmp(attr, attrvalue)) {
+                               ast_xml_free_attr(attr);
+                               return cur;
+                       }
+                       ast_xml_free_attr(attr);
+               }
+       }
+
+       return NULL;
+}
+
+const char *ast_xml_get_text(struct ast_xml_node *node)
+{
+       if (!node) {
+               return NULL;
+       }
+
+       return (const char *) xmlNodeGetContent((xmlNode *) node);
+}
+
+const char *ast_xml_node_get_name(struct ast_xml_node *node)
+{
+       return (const char *) ((xmlNode *) node)->name;
+}
+
+struct ast_xml_node *ast_xml_node_get_children(struct ast_xml_node *node)
+{
+       return (struct ast_xml_node *) ((xmlNode *) node)->children;
+}
+
+struct ast_xml_node *ast_xml_node_get_next(struct ast_xml_node *node)
+{
+       return (struct ast_xml_node *) ((xmlNode *) node)->next;
+}
+
+struct ast_xml_node *ast_xml_node_get_prev(struct ast_xml_node *node)
+{
+       return (struct ast_xml_node *) ((xmlNode *) node)->prev;
+}
+
+struct ast_xml_node *ast_xml_node_get_parent(struct ast_xml_node *node)
+{
+       return (struct ast_xml_node *) ((xmlNode *) node)->parent;
+}
+
+#endif /* defined(HAVE_LIBXML2) */
+
index 59f7f378ddd68248aa0ad3c4ba5b6b7fc6be0657..0b6b3ff42d8927216951f01f1e61e2697db5bce0 100644 (file)
@@ -241,6 +241,9 @@ TERMCAP_INCLUDE=@TERMCAP_INCLUDE@
 TERMCAP_LIB=@TERMCAP_LIB@
 TERMCAP_DIR=@TERMCAP_DIR@
 
+LIBXML2_INCLUDE=@LIBXML2_INCLUDE@
+LIBXML2_LIB=@LIBXML2_LIB@
+
 TINFO_INCLUDE=@TINFO_INCLUDE@
 TINFO_LIB=@TINFO_LIB@
 TINFO_DIR=@TINFO_DIR@