app_queue: Cleanup queue_ref / queue_unref routines.
[asterisk/asterisk.git] / apps / app_chanisavail.c
index 4504d49..70325b3 100644 (file)
  * \ingroup applications
  */
 
-#include "asterisk.h"
+/*** MODULEINFO
+       <support_level>extended</support_level>
+ ***/
 
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+#include "asterisk.h"
 
 #include <sys/ioctl.h>
 
@@ -41,26 +43,61 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/app.h"
 #include "asterisk/devicestate.h"
 
-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";
-
-
-static int chanavail_exec(struct ast_channel *chan, void *data)
+static const char app[] = "ChanIsAvail";
+
+/*** 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 than one enter them as
+                                       Technology2/Resource2&amp;Technology3/Resource3&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 device state for the device</para>
+                               </variable>
+                               <variable name="AVAILCAUSECODE">
+                                       <para>The cause code returned when requesting the channel</para>
+                               </variable>
+                       </variablelist>
+               </description>
+       </application>
+ ***/
+
+static int chanavail_exec(struct ast_channel *chan, const char *data)
 {
        int inuse=-1, option_state=0, string_compare=0, option_all_avail=0;
        int status;
@@ -68,6 +105,7 @@ static int chanavail_exec(struct ast_channel *chan, void *data)
        struct ast_str *tmp_availchan = ast_str_alloca(2048);
        struct ast_str *tmp_availorig = ast_str_alloca(2048);
        struct ast_str *tmp_availstat = ast_str_alloca(2048);
+       struct ast_str *tmp_availcause = ast_str_alloca(2048);
        struct ast_channel *tempchan;
        AST_DECLARE_APP_ARGS(args,
                AST_APP_ARG(reqchans);
@@ -75,7 +113,7 @@ static int chanavail_exec(struct ast_channel *chan, void *data)
        );
 
        if (ast_strlen_zero(data)) {
-               ast_log(LOG_WARNING, "ChanIsAvail requires an argument (Zap/1&Zap/2)\n");
+               ast_log(LOG_WARNING, "ChanIsAvail requires an argument (DAHDI/1&DAHDI/2)\n");
                return -1;
        }
 
@@ -112,7 +150,9 @@ static int chanavail_exec(struct ast_channel *chan, void *data)
                        }
                        *number = '\0';
                        number++;
-                       
+
+                       status = AST_DEVICE_UNKNOWN;
+
                        if (string_compare) {
                                /* ast_parse_device_state checks for "SIP/1234" as a channel name.
                                   ast_device_state will ask the SIP driver for the channel state. */
@@ -127,14 +167,16 @@ static int chanavail_exec(struct ast_channel *chan, void *data)
                                snprintf(trychan, sizeof(trychan), "%s/%s",cur,number);
                                status = inuse = ast_device_state(trychan);
                        }
-                       if ((inuse <= 1) && (tempchan = ast_request(tech, chan->nativeformats, number, &status))) {
-                                       ast_str_append(&tmp_availchan, 0, "%s%s", tmp_availchan->used ? "&" : "", tempchan->name);
-                                       
+                       snprintf(tmp, sizeof(tmp), "%d", status);
+                       ast_str_append(&tmp_availstat, 0, "%s%s", ast_str_strlen(tmp_availstat) ? "&" : "", tmp);
+                       if ((inuse <= 1) && (tempchan = ast_request(tech, ast_channel_nativeformats(chan), NULL, chan, number, &status))) {
+                                       ast_str_append(&tmp_availchan, 0, "%s%s", ast_str_strlen(tmp_availchan) ? "&" : "", ast_channel_name(tempchan));
+
                                        snprintf(tmp, sizeof(tmp), "%s/%s", tech, number);
-                                       ast_str_append(&tmp_availorig, 0, "%s%s", tmp_availorig->used ? "&" : "", tmp);
+                                       ast_str_append(&tmp_availorig, 0, "%s%s", ast_str_strlen(tmp_availorig) ? "&" : "", tmp);
 
                                        snprintf(tmp, sizeof(tmp), "%d", status);
-                                       ast_str_append(&tmp_availstat, 0, "%s%s", tmp_availstat->used ? "&" : "", tmp);
+                                       ast_str_append(&tmp_availcause, 0, "%s%s", ast_str_strlen(tmp_availcause) ? "&" : "", tmp);
 
                                        ast_hangup(tempchan);
                                        tempchan = NULL;
@@ -142,18 +184,16 @@ static int chanavail_exec(struct ast_channel *chan, void *data)
                                        if (!option_all_avail) {
                                                break;
                                        }
-                       } else {
-                               snprintf(tmp, sizeof(tmp), "%d", status);
-                               ast_str_append(&tmp_availstat, 0, "%s%s", tmp_availstat->used ? "&" : "", tmp);
                        }
                        cur = rest;
                } while (cur);
        }
 
-       pbx_builtin_setvar_helper(chan, "AVAILCHAN", tmp_availchan->str);
+       pbx_builtin_setvar_helper(chan, "AVAILCHAN", ast_str_buffer(tmp_availchan));
        /* Store the originally used channel too */
-       pbx_builtin_setvar_helper(chan, "AVAILORIGCHAN", tmp_availorig->str);
-       pbx_builtin_setvar_helper(chan, "AVAILSTATUS", tmp_availstat->str);
+       pbx_builtin_setvar_helper(chan, "AVAILORIGCHAN", ast_str_buffer(tmp_availorig));
+       pbx_builtin_setvar_helper(chan, "AVAILSTATUS", ast_str_buffer(tmp_availstat));
+       pbx_builtin_setvar_helper(chan, "AVAILCAUSECODE", ast_str_buffer(tmp_availcause));
 
        return 0;
 }
@@ -165,7 +205,8 @@ 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;
 }
 
-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Check channel availability");
+AST_MODULE_INFO_STANDARD_EXTENDED(ASTERISK_GPL_KEY, "Check channel availability");