40 #include <sys/ioctl.h>
43 #define ALSA_PCM_NEW_HW_PARAMS_API
44 #define ALSA_PCM_NEW_SW_PARAMS_API
45 #include <alsa/asoundlib.h>
66 .resync_threshold = 1000,
74 #define ALSA_INDEV "default"
75 #define ALSA_OUTDEV "default"
76 #define DESIRED_RATE 8000
79 #define FRAME_SIZE 160
80 #define PERIOD_FRAMES 80
85 #define BUFFER_FMT ((buffersize * 10) << 16) | (0x0006);
88 #define MIN_SWITCH_TIME 600
90 #if __BYTE_ORDER == __LITTLE_ENDIAN
91 static snd_pcm_format_t
format = SND_PCM_FORMAT_S16_LE;
93 static snd_pcm_format_t format = SND_PCM_FORMAT_S16_BE;
104 static const char tdesc[] =
"ALSA Console Channel Driver";
105 static const char config[] =
"alsa.conf";
128 #define MAX_BUFFER_SIZE 100
151 .description =
tdesc,
169 snd_pcm_t *handle = NULL;
170 snd_pcm_hw_params_t *hwparams = NULL;
171 snd_pcm_sw_params_t *swparams = NULL;
174 snd_pcm_uframes_t buffer_size = 0;
176 snd_pcm_uframes_t start_threshold, stop_threshold;
178 err = snd_pcm_open(&handle, dev, stream, SND_PCM_NONBLOCK);
183 ast_debug(1,
"Opening device %s in %s mode\n", dev, (stream == SND_PCM_STREAM_CAPTURE) ?
"read" :
"write");
186 hwparams =
ast_alloca(snd_pcm_hw_params_sizeof());
187 memset(hwparams, 0, snd_pcm_hw_params_sizeof());
188 snd_pcm_hw_params_any(handle, hwparams);
190 err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
194 err = snd_pcm_hw_params_set_format(handle, hwparams, format);
198 err = snd_pcm_hw_params_set_channels(handle, hwparams, 1);
203 err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &rate, &direction);
208 err = snd_pcm_hw_params_set_period_size_near(handle, hwparams, &period_size, &direction);
210 ast_log(
LOG_ERROR,
"period_size(%lu frames) is bad: %s\n", period_size, snd_strerror(err));
212 ast_debug(1,
"Period size is %d\n", err);
215 buffer_size = 4096 * 2;
216 err = snd_pcm_hw_params_set_buffer_size_near(handle, hwparams, &buffer_size);
218 ast_log(
LOG_WARNING,
"Problem setting buffer size of %lu: %s\n", buffer_size, snd_strerror(err));
220 ast_debug(1,
"Buffer size is set to %d frames\n", err);
223 err = snd_pcm_hw_params(handle, hwparams);
225 ast_log(
LOG_ERROR,
"Couldn't set the new hw params: %s\n", snd_strerror(err));
227 swparams =
ast_alloca(snd_pcm_sw_params_sizeof());
228 memset(swparams, 0, snd_pcm_sw_params_sizeof());
229 snd_pcm_sw_params_current(handle, swparams);
231 if (stream == SND_PCM_STREAM_PLAYBACK)
232 start_threshold = period_size;
236 err = snd_pcm_sw_params_set_start_threshold(handle, swparams, start_threshold);
240 if (stream == SND_PCM_STREAM_PLAYBACK)
241 stop_threshold = buffer_size;
243 stop_threshold = buffer_size;
245 err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, stop_threshold);
249 err = snd_pcm_sw_params(handle, swparams);
253 err = snd_pcm_poll_descriptors_count(handle);
255 ast_log(
LOG_ERROR,
"Unable to get a poll descriptors count, error is %s\n", snd_strerror(err));
257 ast_debug(1,
"Can't handle more than one device\n");
260 snd_pcm_poll_descriptors(handle, &pfd, err);
261 ast_debug(1,
"Acquired fd %d from the poll descriptor\n", pfd.fd);
263 if (stream == SND_PCM_STREAM_CAPTURE)
273 if (!noaudiocapture) {
294 ast_verbose(
" << Console Received digit %c of duration %u ms >> \n",
304 ast_verbose(
" << Console Received text %s >> \n", text);
322 ast_verbose(
" << Call placed to '%s' on console >> \n", dest);
335 ast_verbose(
" << Type 'answer' to answer, or use 'autoanswer' for future calls >> \n");
344 if (!noaudiocapture) {
356 ast_verbose(
" << Console call has been answered >> \n");
358 if (!noaudiocapture) {
375 if (!noaudiocapture) {
385 static char sizbuf[8000];
386 static int sizpos = 0;
390 snd_pcm_state_t
state;
395 if (f->
datalen >
sizeof(sizbuf) - sizpos) {
402 if (state == SND_PCM_STATE_XRUN)
404 while ((res = snd_pcm_writei(
alsa.
ocard, sizbuf, len / 2)) == -EAGAIN) {
412 while ((res = snd_pcm_writei(
alsa.
ocard, sizbuf, len / 2)) == -EAGAIN) {
415 if (res != len / 2) {
418 }
else if (res < 0) {
423 if (res == -ESTRPIPE)
431 return res >= 0 ? 0 : res;
440 static int readpos = 0;
442 snd_pcm_state_t
state;
458 if (noaudiocapture) {
465 if ((state != SND_PCM_STATE_PREPARED) && (state != SND_PCM_STATE_RUNNING)) {
471 r = snd_pcm_readi(
alsa.
icard, buf + readpos, left);
477 }
else if (r == -ESTRPIPE) {
557 ast_verbose(
" << Console Has Been Placed on Hold >> \n");
561 ast_verbose(
" << Console Has Been Retrieved from Hold >> \n");
578 if (!(tmp =
ast_channel_alloc(1, state, 0, 0,
"", p->
exten, p->
context, linkedid, 0,
"ALSA/%s", indevname)))
654 e->
command =
"console autoanswer";
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))
670 ast_cli(a->
fd,
"Auto answer is %s.\n", autoanswer ?
"on" :
"off");
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");
720 if (!noaudiocapture) {
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";
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";
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")) {
914 mute = toggle ? !mute : 1;
915 }
else if (!strcasecmp(a->
argv[1],
"unmute")) {
916 mute = toggle ? !mute : 0;
921 ast_cli(a->
fd,
"Console mic is %s\n", mute ?
"off" :
"on");
944 strcpy(mohinterpret,
"default");
947 ast_log(
LOG_ERROR,
"Unable to read ALSA configuration file %s. Aborting.\n", config);
955 for (; v; v = v->
next) {
961 if (!strcasecmp(v->
name,
"autoanswer")) {
963 }
else if (!strcasecmp(v->
name,
"mute")) {
965 }
else if (!strcasecmp(v->
name,
"noaudiocapture")) {
967 }
else if (!strcasecmp(v->
name,
"silencesuppression")) {
969 }
else if (!strcasecmp(v->
name,
"silencethreshold")) {
970 silencethreshold = atoi(v->
value);
971 }
else if (!strcasecmp(v->
name,
"context")) {
973 }
else if (!strcasecmp(v->
name,
"language")) {
975 }
else if (!strcasecmp(v->
name,
"extension")) {
977 }
else if (!strcasecmp(v->
name,
"input_device")) {
979 }
else if (!strcasecmp(v->
name,
"output_device")) {
981 }
else if (!strcasecmp(v->
name,
"mohinterpret")) {
988 ast_verb(2,
"No sound card detected -- console channel will be unavailable\n");
989 ast_verb(2,
"Turn off ALSA support by adding 'noload=chan_alsa.so' in /etc/asterisk/modules.conf\n");
static char * console_dial(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
union ast_frame_subclass subclass
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
struct ast_channel * owner
enum sip_cc_notify_state state
static char mohinterpret[MAX_MUSICCLASS]
static char exten[AST_MAX_EXTENSION]
Main Channel structure associated with a channel.
#define AST_CLI_DEFINE(fn, txt,...)
Asterisk main include file. File version handling, generic pbx functions.
static const char tdesc[]
void ast_module_unref(struct ast_module *)
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame with payload.
char * strsep(char **str, const char *delims)
static struct ast_channel_tech alsa_tech
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
static int silencethreshold
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
static struct ast_channel * alsa_new(struct chan_alsa_pvt *p, int state, const char *linkedid)
static struct chan_alsa_pvt alsa
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
static int alsa_write(struct ast_channel *chan, struct ast_frame *f)
char context[AST_MAX_CONTEXT]
#define DEADLOCK_AVOIDANCE(lock)
descriptor for a cli entry.
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
int ast_jb_read_conf(struct ast_jb_conf *conf, const char *varname, const char *value)
Sets jitterbuffer configuration property.
void ast_verbose(const char *fmt,...)
static struct ast_jb_conf global_jbconf
Structure for variables, used for configurations and for channel variables.
static int noaudiocapture
static int alsa_text(struct ast_channel *c, const char *text)
static int alsa_digit(struct ast_channel *c, char digit, unsigned int duration)
Configuration File Parser.
static char * console_sendtext(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#define ast_mutex_lock(a)
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 ...
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
static char * console_autoanswer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int alsa_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
Common implementation-independent jitterbuffer stuff.
void ast_cli(int fd, const char *fmt,...)
const ast_string_field linkedid
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
#define ast_verb(level,...)
void ast_config_destroy(struct ast_config *config)
Destroys a config.
struct ast_channel * ast_channel_alloc(int needqueue, int state, const char *cid_num, const char *cid_name, const char *acctcode, const char *exten, const char *context, const char *linkedid, const int amaflag, const char *name_fmt,...)
static int alsa_indicate(struct ast_channel *chan, int cond, const void *data, size_t datalen)
String fields in structures.
int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
Queue a hangup frame with hangupcause set.
#define ast_debug(level,...)
Log a DEBUG message.
General Asterisk PBX channel definitions.
#define AST_FRIENDLY_OFFSET
Offset into a frame's data buffer.
#define ast_config_load(filename, flags)
Load a config file.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Asterisk internal frame definitions.
Asterisk architecture endianess compatibility definitions.
#define AST_MAX_EXTENSION
#define AST_CAUSE_NORMAL_CLEARING
static int load_module(void)
int ast_softhangup(struct ast_channel *chan, int reason)
Softly hangup up a channel.
static int soundcard_init(void)
static char language[MAX_LANGUAGE]
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Structure to describe a channel "technology", ie a channel driver See for examples: ...
Core PBX routines and definitions.
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
static int alsa_call(struct ast_channel *c, char *dest, int timeout)
static char outdevname[50]
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
enum ast_channel_state _state
const ast_string_field name
static ast_mutex_t alsalock
char context[AST_MAX_CONTEXT]
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
char exten[AST_MAX_EXTENSION]
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
static char indevname[50]
#define ast_channel_unlock(chan)
static struct ast_cli_entry cli_alsa[]
unsigned int flags
Combination of the AST_JB_ENABLED, AST_JB_FORCED and AST_JB_LOG flags.
static char * console_hangup(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Structure used to handle boolean flags.
static struct ast_frame * alsa_read(struct ast_channel *chan)
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
void ast_jb_configure(struct ast_channel *chan, const struct ast_jb_conf *conf)
Configures a jitterbuffer on a channel.
static char * console_mute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static void grab_owner(void)
static char * autoanswer_complete(const char *line, const char *word, int pos, int state)
#define AST_FORMAT_SLINEAR
Standard Command Line Interface.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
static snd_pcm_t * alsa_card_init(char *dev, snd_pcm_stream_t stream)
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
char * ast_getformatname_multiple(char *buf, size_t size, format_t format)
Get the names of a set of formats.
Data structure associated with a single frame of data.
Internal Asterisk hangup causes.
static const char config[]
enum ast_frame_type frametype
struct ast_variable * next
#define ast_channel_trylock(chan)
static char * console_answer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#define CONFIG_STATUS_FILEINVALID
static char context[AST_MAX_CONTEXT]
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
static int alsa_answer(struct ast_channel *c)
static snd_pcm_format_t format
union ast_frame::@172 data
struct ast_channel_tech * tech
General jitterbuffer configuration.
char exten[AST_MAX_EXTENSION]
#define AST_MUTEX_DEFINE_STATIC(mutex)
static struct ast_channel * alsa_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
static struct ast_jb_conf default_jbconf
static int silencesuppression
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
static int unload_module(void)
#define ast_mutex_unlock(a)
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
struct ast_module * ast_module_ref(struct ast_module *)
static int alsa_hangup(struct ast_channel *c)