[asterisk-commits] russell: branch russell/chan_console r54001 -
/team/russell/chan_console/chan...
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Sun Feb 11 21:15:49 MST 2007
Author: russell
Date: Sun Feb 11 22:15:48 2007
New Revision: 54001
URL: http://svn.digium.com/view/asterisk?view=rev&rev=54001
Log:
Add "console send text" CLI command, among other various formatting and
code cleanup changes ...
Modified:
team/russell/chan_console/channels/chan_console.c
Modified: team/russell/chan_console/channels/chan_console.c
URL: http://svn.digium.com/view/asterisk/team/russell/chan_console/channels/chan_console.c?view=diff&rev=54001&r1=54000&r2=54001
==============================================================================
--- team/russell/chan_console/channels/chan_console.c (original)
+++ team/russell/chan_console/channels/chan_console.c Sun Feb 11 22:15:48 2007
@@ -27,6 +27,23 @@
* chan_alsa, Matthew Fredrickson <creslin at digium.com>
*
* \ingroup channel_drivers
+ *
+ * \note Since this works with any audio system that libportaudio supports,
+ * including ALSA and OSS, this may someday deprecate chan_alsa and chan_oss.
+ * However, before that can be done, it needs to *at least* have all of the
+ * features that these other channel drivers have. The features implemented
+ * in at least one of the other console channel drivers that are not yet
+ * implemented here are:
+ *
+ * Multiple device support
+ * Set Auto-answer from the dialplan
+ *
+ * answer CLI command
+ * flash CLI command
+ * transfer CLI command
+ * autoanswer CLI command (maybe general settings CLIcommand, instead?)
+ * boost CLI command
+ * active CLI command
*/
/*** MODULEINFO
@@ -77,6 +94,12 @@
/*! \brief Mono Output */
#define OUTPUT_CHANNELS 1
+/*
+ * XXX text message sizes are probably 256 chars, but i am
+ * not sure if there is a suitable definition anywhere.
+ */
+#define TEXT_SIZE 256
+
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
@@ -84,7 +107,7 @@
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#endif
-static const char *config_file = "console.conf";
+static const char config_file[] = "console.conf";
/*!
* Each sound is made of 'datalen' samples of sound, repeated as needed to
@@ -100,11 +123,11 @@
const int silencelen;
const int repeat;
} sounds[] = {
- { AST_CONTROL_RINGING, "RINGING", ringtone, sizeof(ringtone)/2, 16000, 32000, 1 },
- { AST_CONTROL_BUSY, "BUSY", busy, sizeof(busy)/2, 4000, 4000, 1 },
- { AST_CONTROL_CONGESTION, "CONGESTION", busy, sizeof(busy)/2, 2000, 2000, 1 },
- { AST_CONTROL_RING, "RING10", ring10, sizeof(ring10)/2, 16000, 32000, 1 },
- { AST_CONTROL_ANSWER, "ANSWER", answer, sizeof(answer)/2, 2200, 0, 0 },
+ { AST_CONTROL_RINGING, "RINGING", ringtone, sizeof(ringtone) / 2, 16000, 32000, 1 },
+ { AST_CONTROL_BUSY, "BUSY", busy, sizeof(busy) / 2, 4000, 4000, 1 },
+ { AST_CONTROL_CONGESTION, "CONGESTION", busy, sizeof(busy) / 2, 2000, 2000, 1 },
+ { AST_CONTROL_RING, "RING10", ring10, sizeof(ring10) / 2, 16000, 32000, 1 },
+ { AST_CONTROL_ANSWER, "ANSWER", answer, sizeof(answer) / 2, 2200, 0, 0 },
{ -1, NULL, 0, 0, 0, 0 }, /* end marker */
};
@@ -161,7 +184,7 @@
ast_mutex_t lock;
/*! List of frames to be written out to the device */
AST_LIST_HEAD_NOLOCK(, ast_frame) frames;
-} pvt = {
+} console_pvt = {
.name = "default",
.lock = AST_MUTEX_INIT_VALUE,
.cursound = -1,
@@ -211,14 +234,14 @@
unsigned long frame_count, const PaStreamCallbackTimeInfo *time_info,
PaStreamCallbackFlags flags, void *userData);
-static int start_stream(void)
+static int start_stream(struct console_pvt *pvt)
{
PaError res;
- if (pvt.streamstate)
+ if (pvt->streamstate)
return 0;
- res = Pa_OpenDefaultStream(&pvt.stream, INPUT_CHANNELS, OUTPUT_CHANNELS,
+ res = Pa_OpenDefaultStream(&pvt->stream, INPUT_CHANNELS, OUTPUT_CHANNELS,
paInt16, SAMPLE_RATE, NUM_SAMPLES, console_callback, NULL);
if (res != paNoError) {
ast_log(LOG_WARNING, "Failed to open default audio device - (%d) %s\n",
@@ -226,14 +249,14 @@
return -1;
}
- res = Pa_StartStream(pvt.stream);
+ res = Pa_StartStream(pvt->stream);
if (res != paNoError) {
ast_log(LOG_WARNING, "Failed to start stream - (%d) %s\n",
res, Pa_GetErrorText(res));
return -1;
}
- pvt.streamstate = 1;
+ pvt->streamstate = 1;
return 0;
}
@@ -241,18 +264,18 @@
/*!
* \note Called with pvt struct locked
*/
-static int stop_stream(void)
-{
- if (!pvt.streamstate)
+static int stop_stream(struct console_pvt *pvt)
+{
+ if (!pvt->streamstate)
return 0;
- ast_mutex_lock(&pvt.lock);
- Pa_AbortStream(pvt.stream);
- Pa_CloseStream(pvt.stream);
- pvt.stream = NULL;
- pvt.streamstate = 0;
- ast_cond_signal(&pvt.cond);
- ast_mutex_unlock(&pvt.lock);
+ ast_mutex_lock(&pvt->lock);
+ Pa_AbortStream(pvt->stream);
+ Pa_CloseStream(pvt->stream);
+ pvt->stream = NULL;
+ pvt->streamstate = 0;
+ ast_cond_signal(&pvt->cond);
+ ast_mutex_unlock(&pvt->lock);
return 0;
}
@@ -297,7 +320,7 @@
ast_hangup(chan);
chan = NULL;
} else
- start_stream();
+ start_stream(pvt);
}
return chan;
@@ -307,6 +330,7 @@
{
int oldformat = format;
struct ast_channel *chan = NULL;
+ struct console_pvt *pvt = &console_pvt;
format &= AST_FORMAT_SLINEAR;
if (!format) {
@@ -314,13 +338,13 @@
return NULL;
}
- ast_mutex_lock(&pvt.lock);
- if (pvt.owner) {
+ ast_mutex_lock(&pvt->lock);
+ if (pvt->owner) {
ast_log(LOG_NOTICE, "Console channel already active!\n");
*cause = AST_CAUSE_BUSY;
- } else if (!(chan = console_new(&pvt, NULL, NULL, AST_STATE_DOWN)))
+ } else if (!(chan = console_new(pvt, NULL, NULL, AST_STATE_DOWN)))
ast_log(LOG_WARNING, "Unable to create new Console channel!\n");
- ast_mutex_unlock(&pvt.lock);
+ ast_mutex_unlock(&pvt->lock);
return chan;
}
@@ -371,23 +395,25 @@
static int console_hangup(struct ast_channel *c)
{
+ struct console_pvt *pvt = &console_pvt;
+
ast_verbose(" --- <(\"<) --- Hangup on Console --- (>\")> ---\n");
- pvt.hookstate = 0;
- set_cursound(&pvt, -1);
+ pvt->hookstate = 0;
+ set_cursound(pvt, -1);
c->tech_pvt = NULL;
- pvt.owner = NULL;
+ pvt->owner = NULL;
/* Wait until the callback has exited before stopping the stream, also
* ensuring that the callback isn't blocking while waiting on a frame. */
- while (pvt.incallback) { /* :( */
- ast_mutex_lock(&pvt.lock);
- ast_cond_signal(&pvt.cond);
- ast_mutex_unlock(&pvt.lock);
+ while (pvt->incallback) { /* :( */
+ ast_mutex_lock(&pvt->lock);
+ ast_cond_signal(&pvt->cond);
+ ast_mutex_unlock(&pvt->lock);
usleep(10);
}
- stop_stream();
+ stop_stream(pvt);
return 0;
}
@@ -395,14 +421,15 @@
static int console_answer(struct ast_channel *c)
{
int res;
+ struct console_pvt *pvt = &console_pvt;
ast_verbose(" --- <(\"<) --- Call from Console has been Answered --- (>\")> ---\n");
- ast_mutex_lock(&pvt.lock);
+ ast_mutex_lock(&pvt->lock);
ast_setstate(c, AST_STATE_UP);
- set_cursound(&pvt, -1);
- res = start_stream();
- ast_mutex_unlock(&pvt.lock);
+ set_cursound(pvt, -1);
+ res = start_stream(pvt);
+ ast_mutex_unlock(&pvt->lock);
return res;
}
@@ -417,13 +444,14 @@
static int console_call(struct ast_channel *c, char *dest, int timeout)
{
struct ast_frame f = { 0, };
+ struct console_pvt *pvt = &console_pvt;
ast_verbose(" --- <(\"<) --- Call to device '%s' on console from '%s' <%s> --- (>\")> ---\n",
dest, c->cid.cid_name, c->cid.cid_num);
- if (pvt.autoanswer) {
+ if (pvt->autoanswer) {
ast_verbose(" --- <(\"<) --- Auto-answered --- (>\")> --- \n");
- pvt.hookstate = 1;
+ pvt->hookstate = 1;
f.frametype = AST_FRAME_CONTROL;
f.subclass = AST_CONTROL_ANSWER;
ast_queue_frame(c, &f);
@@ -432,22 +460,23 @@
f.frametype = AST_FRAME_CONTROL;
f.subclass = AST_CONTROL_RINGING;
ast_queue_frame(c, &f);
- set_cursound(&pvt, AST_CONTROL_RING);
- }
-
- return start_stream();
+ set_cursound(pvt, AST_CONTROL_RING);
+ }
+
+ return start_stream(pvt);
}
static int console_write(struct ast_channel *chan, struct ast_frame *f)
{
struct ast_frame *fr = ast_frdup(f);
+ struct console_pvt *pvt = &console_pvt;
if (!fr)
return -1;
- ast_mutex_lock(&pvt.lock);
- AST_LIST_INSERT_TAIL(&pvt.frames, fr, frame_list);
- ast_cond_signal(&pvt.cond);
- ast_mutex_unlock(&pvt.lock);
+ ast_mutex_lock(&pvt->lock);
+ AST_LIST_INSERT_TAIL(&pvt->frames, fr, frame_list);
+ ast_cond_signal(&pvt->cond);
+ ast_mutex_unlock(&pvt->lock);
return 0;
}
@@ -484,9 +513,11 @@
static int console_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
{
- ast_mutex_lock(&pvt.lock);
- pvt.owner = newchan;
- ast_mutex_unlock(&pvt.lock);
+ struct console_pvt *pvt = &console_pvt;
+
+ ast_mutex_lock(&pvt->lock);
+ pvt->owner = newchan;
+ ast_mutex_unlock(&pvt->lock);
return 0;
}
@@ -632,16 +663,16 @@
PaStreamCallbackFlags flags, void *userData)
{
int res = paContinue;
- struct console_pvt *p = &pvt;
-
- p->incallback = 1;
+ struct console_pvt *pvt = &console_pvt;
+
+ pvt->incallback = 1;
if (output)
- res = handle_output(p, output, frame_count);
+ res = handle_output(pvt, output, frame_count);
if (res != paAbort && input)
- res = handle_input(p, input, frame_count);
-
- p->incallback = 0;
+ res = handle_input(pvt, input, frame_count);
+
+ pvt->incallback = 0;
return res;
}
@@ -655,7 +686,7 @@
* and it is nice not to need it because you have '@' in SIP addresses.
* Return value is the buffer address.
*/
-static char *ast_ext_ctx(const char *src, char **ext, char **ctx)
+static char *ast_ext_ctx(struct console_pvt *pvt, const char *src, char **ext, char **ctx)
{
if (ext == NULL || ctx == NULL)
return NULL; /* error */
@@ -668,7 +699,7 @@
if (*ext == NULL)
return NULL;
- if (!pvt.overridecontext) {
+ if (!pvt->overridecontext) {
/* parse from the right */
*ctx = strrchr(*ext, '@');
if (*ctx)
@@ -681,6 +712,7 @@
static char *cli_console_dial(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
char *s = NULL, *mye = NULL, *myc = NULL;
+ struct console_pvt *pvt = &console_pvt;
if (cmd == CLI_INIT) {
e->command = "console dial";
@@ -693,7 +725,7 @@
if (a->argc > e->args + 1)
return CLI_SHOWUSAGE;
- if (pvt.owner) { /* already in a call */
+ if (pvt->owner) { /* already in a call */
int i;
struct ast_frame f = { AST_FRAME_DTMF, 0 };
@@ -705,23 +737,23 @@
/* send the string one char at a time */
for (i = 0; i < strlen(s); i++) {
f.subclass = s[i];
- ast_queue_frame(pvt.owner, &f);
+ ast_queue_frame(pvt->owner, &f);
}
return CLI_SUCCESS;
}
/* if we have an argument split it into extension and context */
if (a->argc == e->args + 1) {
- s = ast_ext_ctx(a->argv[e->args], &mye, &myc);
+ s = ast_ext_ctx(pvt, a->argv[e->args], &mye, &myc);
ast_log(LOG_NOTICE, "provided '%s', exten '%s' context '%s'\n", a->argv[e->args], mye, myc);
}
/* supply default values if needed */
if (mye == NULL)
- mye = pvt.exten;
+ mye = pvt->exten;
if (myc == NULL)
- myc = pvt.context;
+ myc = pvt->context;
if (ast_exists_extension(NULL, myc, mye, 1, NULL)) {
- pvt.hookstate = 1;
- console_new(&pvt, mye, myc, AST_STATE_RINGING);
+ pvt->hookstate = 1;
+ console_new(pvt, mye, myc, AST_STATE_RINGING);
} else
ast_cli(a->fd, "No such extension '%s' in context '%s'\n", mye, myc);
if (s)
@@ -731,6 +763,8 @@
static char *cli_console_hangup(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
+ struct console_pvt *pvt = &console_pvt;
+
if (cmd == CLI_INIT) {
e->command = "console hangup";
e->usage =
@@ -742,14 +776,14 @@
if (a->argc != e->args)
return CLI_SHOWUSAGE;
- if (!pvt.owner && !pvt.hookstate) {
+ if (!pvt->owner && !pvt->hookstate) {
ast_cli(a->fd, "No call to hang up\n");
return CLI_FAILURE;
}
- pvt.hookstate = 0;
- set_cursound(&pvt, -1);
- if (pvt.owner)
- ast_queue_hangup(pvt.owner);
+ pvt->hookstate = 0;
+ set_cursound(pvt, -1);
+ if (pvt->owner)
+ ast_queue_hangup(pvt->owner);
return CLI_SUCCESS;
}
@@ -757,6 +791,7 @@
static char *cli_console_mute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
char *s;
+ struct console_pvt *pvt = &console_pvt;
if (cmd == CLI_INIT) {
e->command = "console {mute|unmute}";
@@ -771,14 +806,14 @@
return CLI_SHOWUSAGE;
s = a->argv[e->args-1];
if (!strcasecmp(s, "mute"))
- pvt.muted = 1;
+ pvt->muted = 1;
else if (!strcasecmp(s, "unmute"))
- pvt.muted = 0;
+ pvt->muted = 0;
else
return CLI_SHOWUSAGE;
ast_verbose(" --- <(\"<) --- The Console is now %s --- (>\")> ---\n",
- pvt.muted ? "Muted" : "Unmuted");
+ pvt->muted ? "Muted" : "Unmuted");
return CLI_SUCCESS;
}
@@ -822,10 +857,51 @@
return CLI_SUCCESS;
}
+/*!
+ * \brief Console send text CLI command
+ *
+ * \note concatenate all arguments into a single string. argv is NULL-terminated
+ * so we can use it right away
+ */
+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 = &console_pvt;
+
+ if (cmd == CLI_INIT) {
+ e->command = "console send text";
+ e->usage =
+ "Usage: console send text <message>\n"
+ " Sends a text message for display on the remote terminal.\n";
+ return NULL;
+ } else if (cmd == CLI_GENERATE)
+ return NULL;
+
+ if (a->argc < e->args + 1)
+ return CLI_SHOWUSAGE;
+ if (!pvt->owner) {
+ ast_cli(a->fd, "Not in a call\n");
+ return CLI_FAILURE;
+ }
+ ast_join(buf, sizeof(buf) - 1, a->argv + e->args);
+ if (!ast_strlen_zero(buf)) {
+ struct ast_frame f = { 0, };
+ int i = strlen(buf);
+ buf[i] = '\n';
+ f.frametype = AST_FRAME_TEXT;
+ f.subclass = 0;
+ f.data = buf;
+ f.datalen = i + 1;
+ ast_queue_frame(pvt->owner, &f);
+ }
+ return CLI_SUCCESS;
+}
+
static struct ast_cli_entry cli_console[] = {
NEW_CLI(cli_console_dial, "Dial an extension from the console"),
NEW_CLI(cli_console_hangup, "Hangup a call on the console"),
NEW_CLI(cli_console_mute, "Disable/Enable mic input"),
+ NEW_CLI(cli_console_sendtext, "Send text to a connected party"),
NEW_CLI(cli_list_devices, "List available devices"),
};
@@ -839,17 +915,18 @@
{
struct ast_config *cfg;
struct ast_variable *v;
+ struct console_pvt *pvt = &console_pvt;
/* default values */
memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
- strcpy(pvt.mohinterpret, "default");
- strcpy(pvt.context, "default");
- strcpy(pvt.exten, "s");
- pvt.language[0] = '\0';
- pvt.cid_num[0] = '\0';
- pvt.cid_name[0] = '\0';
- pvt.overridecontext = 0;
- pvt.autoanswer = 0;
+ strcpy(pvt->mohinterpret, "default");
+ strcpy(pvt->context, "default");
+ strcpy(pvt->exten, "s");
+ pvt->language[0] = '\0';
+ pvt->cid_num[0] = '\0';
+ pvt->cid_name[0] = '\0';
+ pvt->overridecontext = 0;
+ pvt->autoanswer = 0;
if (!(cfg = ast_config_load(config_file))) {
ast_log(LOG_NOTICE, "Unable to open configuration file %s!\n", config_file);
@@ -860,20 +937,20 @@
if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
continue;
else if (!strcasecmp(v->name, "context"))
- ast_copy_string(pvt.context, v->value, sizeof(pvt.context));
+ ast_copy_string(pvt->context, v->value, sizeof(pvt->context));
else if (!strcasecmp(v->name, "extension"))
- ast_copy_string(pvt.exten, v->value, sizeof(pvt.exten));
+ ast_copy_string(pvt->exten, v->value, sizeof(pvt->exten));
else if (!strcasecmp(v->name, "mohinterpret"))
- ast_copy_string(pvt.mohinterpret, v->value, sizeof(pvt.mohinterpret));
+ ast_copy_string(pvt->mohinterpret, v->value, sizeof(pvt->mohinterpret));
else if (!strcasecmp(v->name, "language"))
- ast_copy_string(pvt.language, v->value, sizeof(pvt.language));
+ ast_copy_string(pvt->language, v->value, sizeof(pvt->language));
else if (!strcasecmp(v->name, "callerid"))
- ast_callerid_split(v->value, pvt.cid_name, sizeof(pvt.cid_name),
- pvt.cid_num, sizeof(pvt.cid_num));
+ ast_callerid_split(v->value, pvt->cid_name, sizeof(pvt->cid_name),
+ pvt->cid_num, sizeof(pvt->cid_num));
else if (!strcasecmp(v->name, "overridecontext"))
- pvt.overridecontext = ast_true(v->value) ? 1 : 0;
+ pvt->overridecontext = ast_true(v->value) ? 1 : 0;
else if (!strcasecmp(v->name, "autoanswer"))
- pvt.autoanswer = ast_true(v->value) ? 1 : 0;
+ pvt->autoanswer = ast_true(v->value) ? 1 : 0;
else
ast_log(LOG_WARNING, "Unknown option '%s' on line '%d' of '%s'!\n",
v->name, v->lineno, config_file);
@@ -885,14 +962,16 @@
static int unload_module(void)
{
- if (pvt.hookstate)
- stop_stream();
+ struct console_pvt *pvt = &console_pvt;
+
+ if (pvt->hookstate)
+ stop_stream(pvt);
Pa_Terminate();
ast_channel_unregister(&console_tech);
ast_cli_unregister_multiple(cli_console, sizeof(cli_console) / sizeof(cli_console[0]));
- ast_cond_destroy(&pvt.cond);
+ ast_cond_destroy(&pvt->cond);
return 0;
}
@@ -900,11 +979,12 @@
static int load_module(void)
{
PaError res;
+ struct console_pvt *pvt = &console_pvt;
if (load_config(0))
return AST_MODULE_LOAD_DECLINE;
- ast_cond_init(&pvt.cond, NULL);
+ ast_cond_init(&pvt->cond, NULL);
res = Pa_Initialize();
if (res != paNoError) {
@@ -915,7 +995,7 @@
if (ast_channel_register(&console_tech)) {
ast_log(LOG_ERROR, "Unable to register channel type 'Console'\n");
- ast_cond_destroy(&pvt.cond);
+ ast_cond_destroy(&pvt->cond);
return AST_MODULE_LOAD_DECLINE;
}
More information about the asterisk-commits
mailing list