48 #define ESTRPIPE EPIPE
51 #include <sys/ioctl.h>
54 #define ALSA_PCM_NEW_HW_PARAMS_API
55 #define ALSA_PCM_NEW_SW_PARAMS_API
56 #include <alsa/asoundlib.h>
79 .resync_threshold = 1000,
87 #define ALSA_INDEV "default"
88 #define ALSA_OUTDEV "default"
89 #define DESIRED_RATE 8000
92 #define FRAME_SIZE 160
93 #define PERIOD_FRAMES 80
98 #define BUFFER_FMT ((buffersize * 10) << 16) | (0x0006);
101 #define MIN_SWITCH_TIME 600
103 #if __BYTE_ORDER == __LITTLE_ENDIAN
104 static snd_pcm_format_t
format = SND_PCM_FORMAT_S16_LE;
106 static snd_pcm_format_t
format = SND_PCM_FORMAT_S16_BE;
117 static const char tdesc[] =
"ALSA Console Channel Driver";
118 static const char config[] =
"alsa.conf";
141 #define MAX_BUFFER_SIZE 100
164 .description =
tdesc,
181 snd_pcm_t *handle =
NULL;
182 snd_pcm_hw_params_t *hwparams =
NULL;
183 snd_pcm_sw_params_t *swparams =
NULL;
186 snd_pcm_uframes_t buffer_size = 0;
188 snd_pcm_uframes_t start_threshold, stop_threshold;
190 err = snd_pcm_open(&handle, dev, stream, SND_PCM_NONBLOCK);
195 ast_debug(1,
"Opening device %s in %s mode\n", dev, (stream == SND_PCM_STREAM_CAPTURE) ?
"read" :
"write");
198 hwparams =
ast_alloca(snd_pcm_hw_params_sizeof());
199 memset(hwparams, 0, snd_pcm_hw_params_sizeof());
200 snd_pcm_hw_params_any(handle, hwparams);
202 err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
206 err = snd_pcm_hw_params_set_format(handle, hwparams,
format);
210 err = snd_pcm_hw_params_set_channels(handle, hwparams, 1);
215 err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &rate, &
direction);
220 err = snd_pcm_hw_params_set_period_size_near(handle, hwparams, &period_size, &
direction);
222 ast_log(
LOG_ERROR,
"period_size(%lu frames) is bad: %s\n", period_size, snd_strerror(err));
224 ast_debug(1,
"Period size is %d\n", err);
227 buffer_size = 4096 * 2;
228 err = snd_pcm_hw_params_set_buffer_size_near(handle, hwparams, &buffer_size);
230 ast_log(
LOG_WARNING,
"Problem setting buffer size of %lu: %s\n", buffer_size, snd_strerror(err));
232 ast_debug(1,
"Buffer size is set to %d frames\n", err);
235 err = snd_pcm_hw_params(handle, hwparams);
237 ast_log(
LOG_ERROR,
"Couldn't set the new hw params: %s\n", snd_strerror(err));
239 swparams =
ast_alloca(snd_pcm_sw_params_sizeof());
240 memset(swparams, 0, snd_pcm_sw_params_sizeof());
241 snd_pcm_sw_params_current(handle, swparams);
243 if (stream == SND_PCM_STREAM_PLAYBACK)
244 start_threshold = period_size;
248 err = snd_pcm_sw_params_set_start_threshold(handle, swparams, start_threshold);
252 if (stream == SND_PCM_STREAM_PLAYBACK)
253 stop_threshold = buffer_size;
255 stop_threshold = buffer_size;
257 err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, stop_threshold);
261 err = snd_pcm_sw_params(handle, swparams);
265 err = snd_pcm_poll_descriptors_count(handle);
267 ast_log(
LOG_ERROR,
"Unable to get a poll descriptors count, error is %s\n", snd_strerror(err));
269 ast_debug(1,
"Can't handle more than one device\n");
272 snd_pcm_poll_descriptors(handle, &pfd, err);
273 ast_debug(1,
"Acquired fd %d from the poll descriptor\n", pfd.fd);
275 if (stream == SND_PCM_STREAM_CAPTURE)
306 ast_verbose(
" << Console Received digit %c of duration %u ms >> \n",
334 ast_verbose(
" << Call placed to '%s' on console >> \n", dest);
347 ast_verbose(
" << Type 'answer' to answer, or use 'autoanswer' for future calls >> \n");
368 ast_verbose(
" << Console call has been answered >> \n");
397 static char sizbuf[8000];
398 static int sizpos = 0;
402 snd_pcm_state_t
state;
407 if (f->
datalen >
sizeof(sizbuf) - sizpos) {
414 if (
state == SND_PCM_STATE_XRUN)
416 while ((res = snd_pcm_writei(
alsa.
ocard, sizbuf,
len / 2)) == -EAGAIN) {
424 while ((res = snd_pcm_writei(
alsa.
ocard, sizbuf,
len / 2)) == -EAGAIN) {
427 if (res !=
len / 2) {
430 }
else if (res < 0) {
443 return res >= 0 ? 0 : res;
452 static int readpos = 0;
454 snd_pcm_state_t
state;
476 if ((
state != SND_PCM_STATE_PREPARED) && (
state != SND_PCM_STATE_RUNNING)) {
567 ast_verbose(
" << Console Has Been Placed on Hold >> \n");
571 ast_verbose(
" << Console Has Been Retrieved from Hold >> \n");
588 if (!(
tmp =
ast_channel_alloc(1,
state, 0, 0,
"", p->
exten, p->
context, assignedids, requestor, 0,
"ALSA/%s",
indevname)))
654 e->
command =
"console autoanswer [on|off]";
656 "Usage: console autoanswer [on|off]\n"
657 " Enables or disables autoanswer feature. If used without\n"
658 " argument, displays the current on/off status of autoanswer.\n"
659 " The default value of autoanswer is in 'alsa.conf'.\n";
665 if ((
a->argc != 2) && (
a->argc != 3))
672 if (!strcasecmp(
a->argv[2],
"on"))
674 else if (!strcasecmp(
a->argv[2],
"off"))
692 "Usage: console answer\n"
693 " Answers an incoming call on the console (ALSA) channel.\n";
706 ast_cli(
a->fd,
"No one is calling us\n");
737 e->
command =
"console send text";
739 "Usage: console send text <message>\n"
740 " Sends a text message for display on the remote terminal.\n";
752 ast_cli(
a->fd,
"No channel active\n");
756 char text2send[256] =
"";
758 while (tmparg < a->argc) {
759 strncat(text2send,
a->argv[tmparg++],
sizeof(text2send) - strlen(text2send) - 1);
760 strncat(text2send,
" ",
sizeof(text2send) - strlen(text2send) - 1);
763 text2send[strlen(text2send) - 1] =
'\n';
765 f.
datalen = strlen(text2send) + 1;
787 "Usage: console hangup\n"
788 " Hangs up any call currently placed on the console.\n";
801 ast_cli(
a->fd,
"No call to hangup\n");
819 char tmp[256], *tmp2;
828 "Usage: console dial [extension[@context]]\n"
829 " Dials a given extension (and context if specified)\n";
835 if ((
a->argc != 2) && (
a->argc != 3))
843 for (
d =
a->argv[2]; *
d;
d++) {
850 ast_cli(
a->fd,
"You're already in a call. You can use this only to dial digits until you hangup\n");
857 char *stringp =
NULL;
862 tmp2 =
strsep(&stringp,
"@");
874 ast_cli(
a->fd,
"No such extension '%s' in context '%s'\n", mye, myc);
889 e->
command =
"console {mute|unmute} [toggle]";
891 "Usage: console {mute|unmute} [toggle]\n"
892 " Mute/unmute the microphone.\n";
904 if (strcasecmp(
a->argv[2],
"toggle"))
913 if (!strcasecmp(
a->argv[1],
"mute")) {
915 }
else if (!strcasecmp(
a->argv[1],
"unmute")) {
921 ast_cli(
a->fd,
"Console mic is %s\n",
mute ?
"off" :
"on");
990 for (; v; v = v->
next) {
996 if (!strcasecmp(v->
name,
"autoanswer")) {
998 }
else if (!strcasecmp(v->
name,
"mute")) {
1000 }
else if (!strcasecmp(v->
name,
"noaudiocapture")) {
1002 }
else if (!strcasecmp(v->
name,
"silencesuppression")) {
1004 }
else if (!strcasecmp(v->
name,
"silencethreshold")) {
1006 }
else if (!strcasecmp(v->
name,
"context")) {
1008 }
else if (!strcasecmp(v->
name,
"language")) {
1010 }
else if (!strcasecmp(v->
name,
"extension")) {
1012 }
else if (!strcasecmp(v->
name,
"input_device")) {
1014 }
else if (!strcasecmp(v->
name,
"output_device")) {
1016 }
else if (!strcasecmp(v->
name,
"mohinterpret")) {
1023 ast_verb(2,
"No sound card detected -- console channel will be unavailable\n");
1024 ast_verb(2,
"Turn off ALSA support by adding 'noload=chan_alsa.so' in /etc/asterisk/modules.conf\n");
Common implementation-independent jitterbuffer stuff.
void ast_jb_configure(struct ast_channel *chan, const struct ast_jb_conf *conf)
Configures a jitterbuffer on a channel.
int ast_jb_read_conf(struct ast_jb_conf *conf, const char *varname, const char *value)
Sets jitterbuffer configuration property.
Asterisk main include file. File version handling, generic pbx functions.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Internal Asterisk hangup causes.
#define AST_CAUSE_NORMAL_CLEARING
static int alsa_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
static struct ast_channel * alsa_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)
static char outdevname[50]
static struct ast_channel * alsa_new(struct chan_alsa_pvt *p, int state, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
static struct ast_jb_conf default_jbconf
static int soundcard_init(void)
static int noaudiocapture
static int alsa_hangup(struct ast_channel *c)
static char indevname[50]
static char * console_answer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static snd_pcm_t * alsa_card_init(char *dev, snd_pcm_stream_t stream)
static void grab_owner(void)
static int silencesuppression
static int alsa_answer(struct ast_channel *c)
static char * console_dial(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static struct ast_channel_tech alsa_tech
static const char tdesc[]
static char exten[AST_MAX_EXTENSION]
static ast_mutex_t alsalock
static char * console_autoanswer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int alsa_call(struct ast_channel *c, const char *dest, int timeout)
static char * console_hangup(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static snd_pcm_format_t format
static const char config[]
static int alsa_digit(struct ast_channel *c, char digit, unsigned int duration)
static struct ast_frame * alsa_read(struct ast_channel *chan)
static int alsa_text(struct ast_channel *c, const char *text)
static char * console_mute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static struct ast_jb_conf global_jbconf
static int silencethreshold
static char context[AST_MAX_CONTEXT]
static int load_module(void)
Load the module.
static int alsa_write(struct ast_channel *chan, struct ast_frame *f)
static int unload_module(void)
static char * console_sendtext(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char language[MAX_LANGUAGE]
static struct ast_cli_entry cli_alsa[]
static char mohinterpret[MAX_MUSICCLASS]
static struct chan_alsa_pvt alsa
static int alsa_indicate(struct ast_channel *chan, int cond, const void *data, size_t datalen)
enum sip_cc_notify_state state
General Asterisk PBX channel definitions.
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
void * ast_channel_tech_pvt(const struct ast_channel *chan)
@ AST_SOFTHANGUP_APPUNLOAD
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
const char * ast_channel_name(const struct ast_channel *chan)
#define ast_channel_trylock(chan)
int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
Queue a hangup frame with hangupcause set.
void ast_channel_tech_pvt_set(struct ast_channel *chan, void *value)
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
void ast_channel_set_readformat(struct ast_channel *chan, struct ast_format *format)
int ast_channel_register(const struct ast_channel_tech *tech)
Register a channel technology (a new channel driver) Called by a channel module to register the kind ...
void ast_channel_context_set(struct ast_channel *chan, const char *value)
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
void ast_channel_tech_set(struct ast_channel *chan, const struct ast_channel_tech *value)
#define ast_channel_unlock(chan)
#define AST_MAX_EXTENSION
void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format)
ast_channel_state
ast_channel states
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Standard Command Line Interface.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
#define AST_CLI_DEFINE(fn, txt,...)
void ast_cli(int fd, const char *fmt,...)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Asterisk architecture endianess compatibility definitions.
void ast_verbose(const char *fmt,...)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
char * strsep(char **str, const char *delims)
Configuration File Parser.
#define ast_config_load(filename, flags)
Load a config file.
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Asterisk internal frame definitions.
#define AST_FRIENDLY_OFFSET
Offset into a frame's data buffer.
@ AST_CONTROL_PVT_CAUSE_CODE
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
#define DEADLOCK_AVOIDANCE(lock)
#define ast_mutex_unlock(a)
#define ast_mutex_lock(a)
#define AST_MUTEX_DEFINE_STATIC(mutex)
Asterisk module definitions.
#define ast_module_unref(mod)
Release a reference to the module.
#define ast_module_ref(mod)
Hold a reference to the module.
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
@ AST_MODPRI_CHANNEL_DRIVER
@ AST_MODULE_SUPPORT_DEPRECATED
#define ASTERISK_GPL_KEY
The text the key() function should return.
@ AST_MODULE_LOAD_SUCCESS
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Core PBX routines and definitions.
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
static force_inline int attribute_pure ast_strlen_zero(const char *s)
#define ast_str_alloca(init_len)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Structure to pass both assignedid values to channel drivers.
Structure to describe a channel "technology", ie a channel driver See for examples:
struct ast_format_cap * capabilities
Main Channel structure associated with a channel.
descriptor for a cli entry.
Structure used to handle boolean flags.
struct ast_format * format
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
union ast_frame::@254 data
enum ast_frame_type frametype
General jitterbuffer configuration.
unsigned int flags
Combination of the AST_JB_ENABLED, AST_JB_FORCED and AST_JB_LOG flags.
Support for dynamic strings.
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
char exten[AST_MAX_EXTENSION]
struct ast_channel * owner
char context[AST_MAX_CONTEXT]