menuselect: Remove ineffective weak attribute detection.
[asterisk/asterisk.git] / channels / chan_console.c
index 5eef4c3..a24a6c8 100644 (file)
  * - console_video support
  */
 
+/*! \li \ref chan_console.c uses the configuration file \ref console.conf
+ * \addtogroup configuration_file
+ */
+
+/*! \page console.conf console.conf
+ * \verbinclude console.conf.sample
+ */
+
 /*** MODULEINFO
        <depend>portaudio</depend>
        <support_level>extended</support_level>
@@ -54,9 +62,7 @@
 
 #include "asterisk.h"
 
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <sys/signal.h>  /* SIGURG */
+#include <signal.h>  /* SIGURG */
 
 #include <portaudio.h>
 
@@ -68,6 +74,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/musiconhold.h"
 #include "asterisk/callerid.h"
 #include "asterisk/astobj2.h"
+#include "asterisk/stasis_channels.h"
+#include "asterisk/format_cache.h"
 
 /*! 
  * \brief The sample rate to request from PortAudio 
@@ -186,7 +194,7 @@ static struct ast_jb_conf global_jbconf;
 
 /*! Channel Technology Callbacks @{ */
 static struct ast_channel *console_request(const char *type, struct ast_format_cap *cap,
-       const struct ast_channel *requestor, const char *data, int *cause);
+       const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause);
 static int console_digit_begin(struct ast_channel *c, char digit);
 static int console_digit_end(struct ast_channel *c, char digit, unsigned int duration);
 static int console_text(struct ast_channel *c, const char *text);
@@ -261,12 +269,12 @@ static void *stream_monitor(void *data)
        PaError res;
        struct ast_frame f = {
                .frametype = AST_FRAME_VOICE,
+               .subclass.format = ast_format_slin16,
                .src = "console_stream_monitor",
                .data.ptr = buf,
                .datalen = sizeof(buf),
                .samples = sizeof(buf) / sizeof(int16_t),
        };
-       ast_format_set(&f.subclass.format, AST_FORMAT_SLINEAR16, 0);
 
        for (;;) {
                pthread_testcancel();
@@ -410,19 +418,30 @@ static int stop_stream(struct console_pvt *pvt)
 /*!
  * \note Called with the pvt struct locked
  */
-static struct ast_channel *console_new(struct console_pvt *pvt, const char *ext, const char *ctx, int state, const char *linkedid)
+static struct ast_channel *console_new(struct console_pvt *pvt, const char *ext, const char *ctx, int state, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
 {
+       struct ast_format_cap *caps;
        struct ast_channel *chan;
 
+       caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+       if (!caps) {
+               return NULL;
+       }
+
        if (!(chan = ast_channel_alloc(1, state, pvt->cid_num, pvt->cid_name, NULL, 
-               ext, ctx, linkedid, 0, "Console/%s", pvt->name))) {
+               ext, ctx, assignedids, requestor, 0, "Console/%s", pvt->name))) {
+               ao2_ref(caps, -1);
                return NULL;
        }
 
+       ast_channel_stage_snapshot(chan);
+
        ast_channel_tech_set(chan, &console_tech);
-       ast_format_set(ast_channel_readformat(chan), AST_FORMAT_SLINEAR16, 0);
-       ast_format_set(ast_channel_writeformat(chan), AST_FORMAT_SLINEAR16, 0);
-       ast_format_cap_add(ast_channel_nativeformats(chan), ast_channel_readformat(chan));
+       ast_channel_set_readformat(chan, ast_format_slin16);
+       ast_channel_set_writeformat(chan, ast_format_slin16);
+       ast_format_cap_append(caps, ast_format_slin16, 0);
+       ast_channel_nativeformats_set(chan, caps);
+       ao2_ref(caps, -1);
        ast_channel_tech_pvt_set(chan, ref_pvt(pvt));
 
        pvt->owner = chan;
@@ -432,6 +451,9 @@ static struct ast_channel *console_new(struct console_pvt *pvt, const char *ext,
 
        ast_jb_configure(chan, &global_jbconf);
 
+       ast_channel_stage_snapshot_done(chan);
+       ast_channel_unlock(chan);
+
        if (state != AST_STATE_DOWN) {
                if (ast_pbx_start(chan)) {
                        ast_channel_hangupcause_set(chan, AST_CAUSE_SWITCH_CONGESTION);
@@ -444,19 +466,20 @@ static struct ast_channel *console_new(struct console_pvt *pvt, const char *ext,
        return chan;
 }
 
-static struct ast_channel *console_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause)
+static struct ast_channel *console_request(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
 {
        struct ast_channel *chan = NULL;
        struct console_pvt *pvt;
-       char buf[512];
 
        if (!(pvt = find_pvt(data))) {
                ast_log(LOG_ERROR, "Console device '%s' not found\n", data);
                return NULL;
        }
 
-       if (!(ast_format_cap_has_joint(cap, console_tech.capabilities))) {
-               ast_log(LOG_NOTICE, "Channel requested with unsupported format(s): '%s'\n", ast_getformatname_multiple(buf, sizeof(buf), cap));
+       if (!(ast_format_cap_iscompatible(cap, console_tech.capabilities))) {
+               struct ast_str *cap_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
+               ast_log(LOG_NOTICE, "Channel requested with unsupported format(s): '%s'\n",
+                       ast_format_cap_get_names(cap, &cap_buf));
                goto return_unref;
        }
 
@@ -467,7 +490,7 @@ static struct ast_channel *console_request(const char *type, struct ast_format_c
        }
 
        console_pvt_lock(pvt);
-       chan = console_new(pvt, NULL, NULL, AST_STATE_DOWN, requestor ? ast_channel_linkedid(requestor) : NULL);
+       chan = console_new(pvt, NULL, NULL, AST_STATE_DOWN, assignedids, requestor);
        console_pvt_unlock(pvt);
 
        if (!chan)
@@ -687,7 +710,7 @@ static struct console_pvt *get_active_pvt(void)
 static char *cli_console_autoanswer(struct ast_cli_entry *e, int cmd, 
        struct ast_cli_args *a)
 {
-       struct console_pvt *pvt = get_active_pvt();
+       struct console_pvt *pvt;
        char *res = CLI_SUCCESS;
 
        switch (cmd) {
@@ -704,6 +727,7 @@ static char *cli_console_autoanswer(struct ast_cli_entry *e, int cmd,
                return NULL;
        }
 
+       pvt = get_active_pvt();
        if (!pvt) {
                ast_cli(a->fd, "No console device is set as active.\n");
                return CLI_FAILURE;
@@ -734,7 +758,7 @@ static char *cli_console_autoanswer(struct ast_cli_entry *e, int cmd,
 
 static char *cli_console_flash(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-       struct console_pvt *pvt = get_active_pvt();
+       struct console_pvt *pvt;
 
        if (cmd == CLI_INIT) {
                e->command = "console flash";
@@ -742,17 +766,20 @@ static char *cli_console_flash(struct ast_cli_entry *e, int cmd, struct ast_cli_
                        "Usage: console flash\n"
                        "       Flashes the call currently placed on the console.\n";
                return NULL;
-       } else if (cmd == CLI_GENERATE)
+       } else if (cmd == CLI_GENERATE) {
                return NULL;
+       }
 
+       if (a->argc != e->args) {
+               return CLI_SHOWUSAGE;
+       }
+
+       pvt = get_active_pvt();
        if (!pvt) {
                ast_cli(a->fd, "No console device is set as active\n");
                return CLI_FAILURE;
        }
 
-       if (a->argc != e->args)
-               return CLI_SHOWUSAGE;
-
        if (!pvt->owner) {
                ast_cli(a->fd, "No call to flash\n");
                unref_pvt(pvt);
@@ -772,7 +799,7 @@ static char *cli_console_dial(struct ast_cli_entry *e, int cmd, struct ast_cli_a
 {
        char *s = NULL;
        const char *mye = NULL, *myc = NULL; 
-       struct console_pvt *pvt = get_active_pvt();
+       struct console_pvt *pvt;
 
        if (cmd == CLI_INIT) {
                e->command = "console dial";
@@ -780,16 +807,19 @@ static char *cli_console_dial(struct ast_cli_entry *e, int cmd, struct ast_cli_a
                        "Usage: console dial [extension[@context]]\n"
                        "       Dials a given extension (and context if specified)\n";
                return NULL;
-       } else if (cmd == CLI_GENERATE)
+       } else if (cmd == CLI_GENERATE) {
                return NULL;
+       }
 
+       if (a->argc > e->args + 1) {
+               return CLI_SHOWUSAGE;
+       }
+
+       pvt = get_active_pvt();
        if (!pvt) {
                ast_cli(a->fd, "No console device is currently set as active\n");
                return CLI_FAILURE;
        }
-       
-       if (a->argc > e->args + 1)
-               return CLI_SHOWUSAGE;
 
        if (pvt->owner) {       /* already in a call */
                int i;
@@ -830,12 +860,12 @@ static char *cli_console_dial(struct ast_cli_entry *e, int cmd, struct ast_cli_a
        if (ast_exists_extension(NULL, myc, mye, 1, NULL)) {
                console_pvt_lock(pvt);
                pvt->hookstate = 1;
-               console_new(pvt, mye, myc, AST_STATE_RINGING, NULL);
+               console_new(pvt, mye, myc, AST_STATE_RINGING, NULL, NULL);
                console_pvt_unlock(pvt);
        } else
                ast_cli(a->fd, "No such extension '%s' in context '%s'\n", mye, myc);
 
-       free(s);
+       ast_free(s);
 
        unref_pvt(pvt);
 
@@ -844,7 +874,7 @@ static char *cli_console_dial(struct ast_cli_entry *e, int cmd, struct ast_cli_a
 
 static char *cli_console_hangup(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-       struct console_pvt *pvt = get_active_pvt();
+       struct console_pvt *pvt;
 
        if (cmd == CLI_INIT) {
                e->command = "console hangup";
@@ -852,16 +882,19 @@ static char *cli_console_hangup(struct ast_cli_entry *e, int cmd, struct ast_cli
                        "Usage: console hangup\n"
                        "       Hangs up any call currently placed on the console.\n";
                return NULL;
-       } else if (cmd == CLI_GENERATE)
+       } else if (cmd == CLI_GENERATE) {
                return NULL;
+       }
+
+       if (a->argc != e->args) {
+               return CLI_SHOWUSAGE;
+       }
 
+       pvt = get_active_pvt();
        if (!pvt) {
                ast_cli(a->fd, "No console device is set as active\n");
                return CLI_FAILURE;
        }
-       
-       if (a->argc != e->args)
-               return CLI_SHOWUSAGE;
 
        if (!pvt->owner && !pvt->hookstate) {
                ast_cli(a->fd, "No call to hang up\n");
@@ -881,7 +914,7 @@ static char *cli_console_hangup(struct ast_cli_entry *e, int cmd, struct ast_cli
 static char *cli_console_mute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        const char *s;
-       struct console_pvt *pvt = get_active_pvt();
+       struct console_pvt *pvt;
        char *res = CLI_SUCCESS;
 
        if (cmd == CLI_INIT) {
@@ -890,17 +923,20 @@ static char *cli_console_mute(struct ast_cli_entry *e, int cmd, struct ast_cli_a
                        "Usage: console {mute|unmute}\n"
                        "       Mute/unmute the microphone.\n";
                return NULL;
-       } else if (cmd == CLI_GENERATE)
+       } else if (cmd == CLI_GENERATE) {
                return NULL;
+       }
 
+       if (a->argc != e->args) {
+               return CLI_SHOWUSAGE;
+       }
+
+       pvt = get_active_pvt();
        if (!pvt) {
                ast_cli(a->fd, "No console device is set as active\n");
                return CLI_FAILURE;
        }
 
-       if (a->argc != e->args)
-               return CLI_SHOWUSAGE;
-
        s = a->argv[e->args-1];
        if (!strcasecmp(s, "mute"))
                pvt->muted = 1;
@@ -1028,7 +1064,7 @@ static char *cli_list_devices(struct ast_cli_entry *e, int cmd, struct ast_cli_a
  */
 static char *cli_console_answer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-       struct console_pvt *pvt = get_active_pvt();
+       struct console_pvt *pvt;
 
        switch (cmd) {
        case CLI_INIT:
@@ -1042,6 +1078,7 @@ static char *cli_console_answer(struct ast_cli_entry *e, int cmd, struct ast_cli
                return NULL;    /* no completion */
        }
 
+       pvt = get_active_pvt();
        if (!pvt) {
                ast_cli(a->fd, "No console device is set as active\n");
                return CLI_FAILURE;
@@ -1078,7 +1115,7 @@ static char *cli_console_answer(struct ast_cli_entry *e, int cmd, struct ast_cli
 static char *cli_console_sendtext(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        char buf[TEXT_SIZE];
-       struct console_pvt *pvt = get_active_pvt();
+       struct console_pvt *pvt;
        struct ast_frame f = {
                .frametype = AST_FRAME_TEXT,
                .data.ptr = buf,
@@ -1092,9 +1129,11 @@ static char *cli_console_sendtext(struct ast_cli_entry *e, int cmd, struct ast_c
                        "Usage: console send text <message>\n"
                        "       Sends a text message for display on the remote terminal.\n";
                return NULL;
-       } else if (cmd == CLI_GENERATE)
+       } else if (cmd == CLI_GENERATE) {
                return NULL;
+       }
 
+       pvt = get_active_pvt();
        if (!pvt) {
                ast_cli(a->fd, "No console device is set as active\n");
                return CLI_FAILURE;
@@ -1453,7 +1492,8 @@ static void stop_streams(void)
 
 static int unload_module(void)
 {
-       console_tech.capabilities = ast_format_cap_destroy(console_tech.capabilities);
+       ao2_ref(console_tech.capabilities, -1);
+       console_tech.capabilities = NULL;
        ast_channel_unregister(&console_tech);
        ast_cli_unregister_multiple(cli_console, ARRAY_LEN(cli_console));
 
@@ -1469,15 +1509,24 @@ static int unload_module(void)
        return 0;
 }
 
+/*!
+ * \brief Load the module
+ *
+ * Module loading including tests for configuration or dependencies.
+ * This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
+ * or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
+ * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the 
+ * configuration file or other non-critical problem return 
+ * AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
+ */
 static int load_module(void)
 {
-       struct ast_format tmpfmt;
        PaError res;
 
-       if (!(console_tech.capabilities = ast_format_cap_alloc())) {
+       if (!(console_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
                return AST_MODULE_LOAD_DECLINE;
        }
-       ast_format_cap_add(console_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR16, 0));
+       ast_format_cap_append(console_tech.capabilities, ast_format_slin16, 0);
 
        init_pvt(&globals, NULL);
 
@@ -1514,6 +1563,8 @@ return_error:
        if (pvts)
                ao2_ref(pvts, -1);
        pvts = NULL;
+       ao2_ref(console_tech.capabilities, -1);
+       console_tech.capabilities = NULL;
        pvt_destructor(&globals);
 
        return AST_MODULE_LOAD_DECLINE;
@@ -1525,8 +1576,9 @@ static int reload(void)
 }
 
 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Console Channel Driver",
-               .load = load_module,
-               .unload = unload_module,
-               .reload = reload,
-               .load_pri = AST_MODPRI_CHANNEL_DRIVER,
+       .support_level = AST_MODULE_SUPPORT_EXTENDED,
+       .load = load_module,
+       .unload = unload_module,
+       .reload = reload,
+       .load_pri = AST_MODPRI_CHANNEL_DRIVER,
 );