|
|
|
@ -129,6 +129,8 @@ static int readdev = -1;
|
|
|
|
|
static int writedev = -1;
|
|
|
|
|
|
|
|
|
|
static int autoanswer = 1;
|
|
|
|
|
static int mute = 0;
|
|
|
|
|
static int noaudiocapture = 0;
|
|
|
|
|
|
|
|
|
|
static struct ast_channel *alsa_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
|
|
|
|
|
static int alsa_digit(struct ast_channel *c, char digit, unsigned int duration);
|
|
|
|
@ -265,15 +267,22 @@ static snd_pcm_t *alsa_card_init(char *dev, snd_pcm_stream_t stream)
|
|
|
|
|
|
|
|
|
|
static int soundcard_init(void)
|
|
|
|
|
{
|
|
|
|
|
alsa.icard = alsa_card_init(indevname, SND_PCM_STREAM_CAPTURE);
|
|
|
|
|
if (!noaudiocapture) {
|
|
|
|
|
alsa.icard = alsa_card_init(indevname, SND_PCM_STREAM_CAPTURE);
|
|
|
|
|
if (!alsa.icard) {
|
|
|
|
|
ast_log(LOG_ERROR, "Problem opening alsa capture device\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
alsa.ocard = alsa_card_init(outdevname, SND_PCM_STREAM_PLAYBACK);
|
|
|
|
|
|
|
|
|
|
if (!alsa.icard || !alsa.ocard) {
|
|
|
|
|
ast_log(LOG_ERROR, "Problem opening ALSA I/O devices\n");
|
|
|
|
|
if (!alsa.ocard) {
|
|
|
|
|
ast_log(LOG_ERROR, "Problem opening ALSA playback device\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return readdev;
|
|
|
|
|
return writedev;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int alsa_digit(struct ast_channel *c, char digit, unsigned int duration)
|
|
|
|
@ -310,6 +319,9 @@ static int alsa_call(struct ast_channel *c, char *dest, int timeout)
|
|
|
|
|
ast_verbose(" << Call placed to '%s' on console >> \n", dest);
|
|
|
|
|
if (autoanswer) {
|
|
|
|
|
ast_verbose(" << Auto-answered >> \n");
|
|
|
|
|
if (mute) {
|
|
|
|
|
ast_verbose( " << Muted >> \n" );
|
|
|
|
|
}
|
|
|
|
|
grab_owner();
|
|
|
|
|
if (alsa.owner) {
|
|
|
|
|
f.subclass.integer = AST_CONTROL_ANSWER;
|
|
|
|
@ -326,8 +338,10 @@ static int alsa_call(struct ast_channel *c, char *dest, int timeout)
|
|
|
|
|
ast_indicate(alsa.owner, AST_CONTROL_RINGING);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
snd_pcm_prepare(alsa.icard);
|
|
|
|
|
snd_pcm_start(alsa.icard);
|
|
|
|
|
if (!noaudiocapture) {
|
|
|
|
|
snd_pcm_prepare(alsa.icard);
|
|
|
|
|
snd_pcm_start(alsa.icard);
|
|
|
|
|
}
|
|
|
|
|
ast_mutex_unlock(&alsalock);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
@ -338,8 +352,10 @@ static int alsa_answer(struct ast_channel *c)
|
|
|
|
|
ast_mutex_lock(&alsalock);
|
|
|
|
|
ast_verbose(" << Console call has been answered >> \n");
|
|
|
|
|
ast_setstate(c, AST_STATE_UP);
|
|
|
|
|
snd_pcm_prepare(alsa.icard);
|
|
|
|
|
snd_pcm_start(alsa.icard);
|
|
|
|
|
if (!noaudiocapture) {
|
|
|
|
|
snd_pcm_prepare(alsa.icard);
|
|
|
|
|
snd_pcm_start(alsa.icard);
|
|
|
|
|
}
|
|
|
|
|
ast_mutex_unlock(&alsalock);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
@ -353,7 +369,9 @@ static int alsa_hangup(struct ast_channel *c)
|
|
|
|
|
ast_verbose(" << Hangup on console >> \n");
|
|
|
|
|
ast_module_unref(ast_module_info->self);
|
|
|
|
|
hookstate = 0;
|
|
|
|
|
snd_pcm_drop(alsa.icard);
|
|
|
|
|
if (!noaudiocapture) {
|
|
|
|
|
snd_pcm_drop(alsa.icard);
|
|
|
|
|
}
|
|
|
|
|
ast_mutex_unlock(&alsalock);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
@ -436,6 +454,12 @@ static struct ast_frame *alsa_read(struct ast_channel *chan)
|
|
|
|
|
f.delivery.tv_sec = 0;
|
|
|
|
|
f.delivery.tv_usec = 0;
|
|
|
|
|
|
|
|
|
|
if (noaudiocapture) {
|
|
|
|
|
/* Return null frame to asterisk*/
|
|
|
|
|
ast_mutex_unlock(&alsalock);
|
|
|
|
|
return &f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
state = snd_pcm_state(alsa.icard);
|
|
|
|
|
if ((state != SND_PCM_STATE_PREPARED) && (state != SND_PCM_STATE_RUNNING)) {
|
|
|
|
|
snd_pcm_prepare(alsa.icard);
|
|
|
|
@ -470,6 +494,12 @@ static struct ast_frame *alsa_read(struct ast_channel *chan)
|
|
|
|
|
ast_mutex_unlock(&alsalock);
|
|
|
|
|
return &f;
|
|
|
|
|
}
|
|
|
|
|
if (mute) {
|
|
|
|
|
/* Don't transmit if muted */
|
|
|
|
|
ast_mutex_unlock(&alsalock);
|
|
|
|
|
return &f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
f.frametype = AST_FRAME_VOICE;
|
|
|
|
|
f.subclass.codec = AST_FORMAT_SLINEAR;
|
|
|
|
|
f.samples = FRAME_SIZE;
|
|
|
|
@ -667,6 +697,9 @@ static char *console_answer(struct ast_cli_entry *e, int cmd, struct ast_cli_arg
|
|
|
|
|
ast_cli(a->fd, "No one is calling us\n");
|
|
|
|
|
res = CLI_FAILURE;
|
|
|
|
|
} else {
|
|
|
|
|
if (mute) {
|
|
|
|
|
ast_verbose( " << Muted >> \n" );
|
|
|
|
|
}
|
|
|
|
|
hookstate = 1;
|
|
|
|
|
grab_owner();
|
|
|
|
|
if (alsa.owner) {
|
|
|
|
@ -675,8 +708,10 @@ static char *console_answer(struct ast_cli_entry *e, int cmd, struct ast_cli_arg
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
snd_pcm_prepare(alsa.icard);
|
|
|
|
|
snd_pcm_start(alsa.icard);
|
|
|
|
|
if (!noaudiocapture) {
|
|
|
|
|
snd_pcm_prepare(alsa.icard);
|
|
|
|
|
snd_pcm_start(alsa.icard);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ast_mutex_unlock(&alsalock);
|
|
|
|
|
|
|
|
|
@ -835,12 +870,57 @@ static char *console_dial(struct ast_cli_entry *e, int cmd, struct ast_cli_args
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char *console_mute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
|
|
|
|
{
|
|
|
|
|
int toggle = 0;
|
|
|
|
|
char *res = CLI_SUCCESS;
|
|
|
|
|
|
|
|
|
|
switch (cmd) {
|
|
|
|
|
case CLI_INIT:
|
|
|
|
|
e->command = "console {mute|unmute} [toggle]";
|
|
|
|
|
e->usage =
|
|
|
|
|
"Usage: console {mute|unmute} [toggle]\n"
|
|
|
|
|
" Mute/unmute the microphone.\n";
|
|
|
|
|
return NULL;
|
|
|
|
|
case CLI_GENERATE:
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (a->argc > 3) {
|
|
|
|
|
return CLI_SHOWUSAGE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (a->argc == 3) {
|
|
|
|
|
if (strcasecmp(a->argv[2], "toggle"))
|
|
|
|
|
return CLI_SHOWUSAGE;
|
|
|
|
|
toggle = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (a->argc < 2) {
|
|
|
|
|
return CLI_SHOWUSAGE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!strcasecmp(a->argv[1], "mute")) {
|
|
|
|
|
mute = toggle ? !mute : 1;
|
|
|
|
|
} else if (!strcasecmp(a->argv[1], "unmute")) {
|
|
|
|
|
mute = toggle ? !mute : 0;
|
|
|
|
|
} else {
|
|
|
|
|
return CLI_SHOWUSAGE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ast_cli(a->fd, "Console mic is %s\n", mute ? "off" : "on");
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static struct ast_cli_entry cli_alsa[] = {
|
|
|
|
|
AST_CLI_DEFINE(console_answer, "Answer an incoming console call"),
|
|
|
|
|
AST_CLI_DEFINE(console_hangup, "Hangup a call on the console"),
|
|
|
|
|
AST_CLI_DEFINE(console_dial, "Dial an extension on the console"),
|
|
|
|
|
AST_CLI_DEFINE(console_sendtext, "Send text to the remote device"),
|
|
|
|
|
AST_CLI_DEFINE(console_autoanswer, "Sets/displays autoanswer"),
|
|
|
|
|
AST_CLI_DEFINE(console_mute, "Disable/Enable mic input"),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static int load_module(void)
|
|
|
|
@ -865,27 +945,33 @@ static int load_module(void)
|
|
|
|
|
v = ast_variable_browse(cfg, "general");
|
|
|
|
|
for (; v; v = v->next) {
|
|
|
|
|
/* handle jb conf */
|
|
|
|
|
if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (!strcasecmp(v->name, "autoanswer"))
|
|
|
|
|
if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!strcasecmp(v->name, "autoanswer")) {
|
|
|
|
|
autoanswer = ast_true(v->value);
|
|
|
|
|
else if (!strcasecmp(v->name, "silencesuppression"))
|
|
|
|
|
} else if (!strcasecmp(v->name, "mute")) {
|
|
|
|
|
mute = ast_true(v->value);
|
|
|
|
|
} else if (!strcasecmp(v->name, "noaudiocapture")) {
|
|
|
|
|
noaudiocapture = ast_true(v->value);
|
|
|
|
|
} else if (!strcasecmp(v->name, "silencesuppression")) {
|
|
|
|
|
silencesuppression = ast_true(v->value);
|
|
|
|
|
else if (!strcasecmp(v->name, "silencethreshold"))
|
|
|
|
|
} else if (!strcasecmp(v->name, "silencethreshold")) {
|
|
|
|
|
silencethreshold = atoi(v->value);
|
|
|
|
|
else if (!strcasecmp(v->name, "context"))
|
|
|
|
|
} else if (!strcasecmp(v->name, "context")) {
|
|
|
|
|
ast_copy_string(context, v->value, sizeof(context));
|
|
|
|
|
else if (!strcasecmp(v->name, "language"))
|
|
|
|
|
} else if (!strcasecmp(v->name, "language")) {
|
|
|
|
|
ast_copy_string(language, v->value, sizeof(language));
|
|
|
|
|
else if (!strcasecmp(v->name, "extension"))
|
|
|
|
|
} else if (!strcasecmp(v->name, "extension")) {
|
|
|
|
|
ast_copy_string(exten, v->value, sizeof(exten));
|
|
|
|
|
else if (!strcasecmp(v->name, "input_device"))
|
|
|
|
|
} else if (!strcasecmp(v->name, "input_device")) {
|
|
|
|
|
ast_copy_string(indevname, v->value, sizeof(indevname));
|
|
|
|
|
else if (!strcasecmp(v->name, "output_device"))
|
|
|
|
|
} else if (!strcasecmp(v->name, "output_device")) {
|
|
|
|
|
ast_copy_string(outdevname, v->value, sizeof(outdevname));
|
|
|
|
|
else if (!strcasecmp(v->name, "mohinterpret"))
|
|
|
|
|
} else if (!strcasecmp(v->name, "mohinterpret")) {
|
|
|
|
|
ast_copy_string(mohinterpret, v->value, sizeof(mohinterpret));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ast_config_destroy(cfg);
|
|
|
|
|
|
|
|
|
|