core: Don't allow free to mean ast_free (and malloc, etc..).
[asterisk/asterisk.git] / channels / chan_console.c
index a0eddbe..7ddbcf0 100644 (file)
@@ -29,7 +29,7 @@
  * 
  * \ingroup channel_drivers
  *
- * \extref Portaudio http://www.portaudio.com/
+ * Portaudio http://www.portaudio.com/
  *
  * To install portaudio v19 from svn, check it out using the following command:
  *  - svn co https://www.portaudio.com/repos/portaudio/branches/v19-devel
  * - 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>
@@ -68,6 +76,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,14 +196,14 @@ 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, void *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);
 static int console_hangup(struct ast_channel *c);
 static int console_answer(struct ast_channel *c);
 static struct ast_frame *console_read(struct ast_channel *chan);
-static int console_call(struct ast_channel *c, char *dest, int timeout);
+static int console_call(struct ast_channel *c, const char *dest, int timeout);
 static int console_write(struct ast_channel *chan, struct ast_frame *f);
 static int console_indicate(struct ast_channel *chan, int cond, 
        const void *data, size_t datalen);
@@ -261,12 +271,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,31 +420,45 @@ 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;
        }
 
-       chan->tech = &console_tech;
-       ast_format_set(&chan->readformat, AST_FORMAT_SLINEAR16, 0);
-       ast_format_set(&chan->writeformat, AST_FORMAT_SLINEAR16, 0);
-       ast_format_cap_add(chan->nativeformats, &chan->readformat);
-       chan->tech_pvt = ref_pvt(pvt);
+       ast_channel_stage_snapshot(chan);
+
+       ast_channel_tech_set(chan, &console_tech);
+       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;
 
        if (!ast_strlen_zero(pvt->language))
-               ast_string_field_set(chan, language, pvt->language);
+               ast_channel_language_set(chan, pvt->language);
 
        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)) {
-                       chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
+                       ast_channel_hangupcause_set(chan, AST_CAUSE_SWITCH_CONGESTION);
                        ast_hangup(chan);
                        chan = NULL;
                } else
@@ -444,19 +468,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, void *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", (char *) 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(64);
+               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 +492,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 ? requestor->linkedid : NULL);
+       chan = console_new(pvt, NULL, NULL, AST_STATE_DOWN, assignedids, requestor);
        console_pvt_unlock(pvt);
 
        if (!chan)
@@ -503,7 +528,7 @@ static int console_text(struct ast_channel *c, const char *text)
 
 static int console_hangup(struct ast_channel *c)
 {
-       struct console_pvt *pvt = c->tech_pvt;
+       struct console_pvt *pvt = ast_channel_tech_pvt(c);
 
        ast_verb(1, V_BEGIN "Hangup on Console" V_END);
 
@@ -511,14 +536,14 @@ static int console_hangup(struct ast_channel *c)
        pvt->owner = NULL;
        stop_stream(pvt);
 
-       c->tech_pvt = unref_pvt(pvt);
+       ast_channel_tech_pvt_set(c, unref_pvt(pvt));
 
        return 0;
 }
 
 static int console_answer(struct ast_channel *c)
 {
-       struct console_pvt *pvt = c->tech_pvt;
+       struct console_pvt *pvt = ast_channel_tech_pvt(c);
 
        ast_verb(1, V_BEGIN "Call from Console has been Answered" V_END);
 
@@ -554,15 +579,15 @@ static struct ast_frame *console_read(struct ast_channel *chan)
        return &ast_null_frame;
 }
 
-static int console_call(struct ast_channel *c, char *dest, int timeout)
+static int console_call(struct ast_channel *c, const char *dest, int timeout)
 {
-       struct console_pvt *pvt = c->tech_pvt;
+       struct console_pvt *pvt = ast_channel_tech_pvt(c);
        enum ast_control_frame_type ctrl;
 
        ast_verb(1, V_BEGIN "Call to device '%s' on console from '%s' <%s>" V_END,
                dest,
-               S_COR(c->caller.id.name.valid, c->caller.id.name.str, ""),
-               S_COR(c->caller.id.number.valid, c->caller.id.number.str, ""));
+               S_COR(ast_channel_caller(c)->id.name.valid, ast_channel_caller(c)->id.name.str, ""),
+               S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, ""));
 
        console_pvt_lock(pvt);
 
@@ -586,7 +611,7 @@ static int console_call(struct ast_channel *c, char *dest, int timeout)
 
 static int console_write(struct ast_channel *chan, struct ast_frame *f)
 {
-       struct console_pvt *pvt = chan->tech_pvt;
+       struct console_pvt *pvt = ast_channel_tech_pvt(chan);
 
        Pa_WriteStream(pvt->stream, f->data.ptr, f->samples);
 
@@ -595,13 +620,15 @@ static int console_write(struct ast_channel *chan, struct ast_frame *f)
 
 static int console_indicate(struct ast_channel *chan, int cond, const void *data, size_t datalen)
 {
-       struct console_pvt *pvt = chan->tech_pvt;
+       struct console_pvt *pvt = ast_channel_tech_pvt(chan);
        int res = 0;
 
        switch (cond) {
        case AST_CONTROL_BUSY:
        case AST_CONTROL_CONGESTION:
        case AST_CONTROL_RINGING:
+       case AST_CONTROL_INCOMPLETE:
+       case AST_CONTROL_PVT_CAUSE_CODE:
        case -1:
                res = -1;  /* Ask for inband indications */
                break;
@@ -620,7 +647,7 @@ static int console_indicate(struct ast_channel *chan, int cond, const void *data
                break;
        default:
                ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", 
-                       cond, chan->name);
+                       cond, ast_channel_name(chan));
                /* The core will play inband indications for us if appropriate */
                res = -1;
        }
@@ -630,7 +657,7 @@ static int console_indicate(struct ast_channel *chan, int cond, const void *data
 
 static int console_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
 {
-       struct console_pvt *pvt = newchan->tech_pvt;
+       struct console_pvt *pvt = ast_channel_tech_pvt(newchan);
 
        pvt->owner = newchan;
 
@@ -828,12 +855,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);
 
@@ -1451,7 +1478,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));
 
@@ -1467,15 +1495,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);
 
@@ -1512,6 +1549,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;
@@ -1523,6 +1562,7 @@ static int reload(void)
 }
 
 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Console Channel Driver",
+               .support_level = AST_MODULE_SUPPORT_EXTENDED,
                .load = load_module,
                .unload = unload_module,
                .reload = reload,