Wed Jan 8 2020 09:49:43

Asterisk developer's documentation


chan_alsa.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * By Matthew Fredrickson <creslin@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*! \file
20  * \brief ALSA sound card channel driver
21  *
22  * \author Matthew Fredrickson <creslin@digium.com>
23  *
24  * \par See also
25  * \arg Config_alsa
26  *
27  * \ingroup channel_drivers
28  */
29 
30 /*** MODULEINFO
31  <depend>alsa</depend>
32  <support_level>extended</support_level>
33  ***/
34 
35 #include "asterisk.h"
36 
37 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 413586 $")
38 
39 #include <fcntl.h>
40 #include <sys/ioctl.h>
41 #include <sys/time.h>
42 
43 #define ALSA_PCM_NEW_HW_PARAMS_API
44 #define ALSA_PCM_NEW_SW_PARAMS_API
45 #include <alsa/asoundlib.h>
46 
47 #include "asterisk/frame.h"
48 #include "asterisk/channel.h"
49 #include "asterisk/module.h"
50 #include "asterisk/pbx.h"
51 #include "asterisk/config.h"
52 #include "asterisk/cli.h"
53 #include "asterisk/utils.h"
54 #include "asterisk/causes.h"
55 #include "asterisk/endian.h"
56 #include "asterisk/stringfields.h"
57 #include "asterisk/abstract_jb.h"
58 #include "asterisk/musiconhold.h"
59 #include "asterisk/poll-compat.h"
60 
61 /*! Global jitterbuffer configuration - by default, jb is disabled
62  * \note Values shown here match the defaults shown in alsa.conf.sample */
63 static struct ast_jb_conf default_jbconf = {
64  .flags = 0,
65  .max_size = 200,
66  .resync_threshold = 1000,
67  .impl = "fixed",
68  .target_extra = 40,
69 };
70 static struct ast_jb_conf global_jbconf;
71 
72 #define DEBUG 0
73 /* Which device to use */
74 #define ALSA_INDEV "default"
75 #define ALSA_OUTDEV "default"
76 #define DESIRED_RATE 8000
77 
78 /* Lets use 160 sample frames, just like GSM. */
79 #define FRAME_SIZE 160
80 #define PERIOD_FRAMES 80 /* 80 Frames, at 2 bytes each */
81 
82 /* When you set the frame size, you have to come up with
83  the right buffer format as well. */
84 /* 5 64-byte frames = one frame */
85 #define BUFFER_FMT ((buffersize * 10) << 16) | (0x0006);
86 
87 /* Don't switch between read/write modes faster than every 300 ms */
88 #define MIN_SWITCH_TIME 600
89 
90 #if __BYTE_ORDER == __LITTLE_ENDIAN
91 static snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
92 #else
93 static snd_pcm_format_t format = SND_PCM_FORMAT_S16_BE;
94 #endif
95 
96 static char indevname[50] = ALSA_INDEV;
97 static char outdevname[50] = ALSA_OUTDEV;
98 
99 static int silencesuppression = 0;
100 static int silencethreshold = 1000;
101 
103 
104 static const char tdesc[] = "ALSA Console Channel Driver";
105 static const char config[] = "alsa.conf";
106 
107 static char context[AST_MAX_CONTEXT] = "default";
108 static char language[MAX_LANGUAGE] = "";
109 static char exten[AST_MAX_EXTENSION] = "s";
111 
112 static int hookstate = 0;
113 
114 static struct chan_alsa_pvt {
115  /* We only have one ALSA structure -- near sighted perhaps, but it
116  keeps this driver as simple as possible -- as it should be. */
118  char exten[AST_MAX_EXTENSION];
119  char context[AST_MAX_CONTEXT];
120  snd_pcm_t *icard, *ocard;
121 
122 } alsa;
123 
124 /* Number of buffers... Each is FRAMESIZE/8 ms long. For example
125  with 160 sample frames, and a buffer size of 3, we have a 60ms buffer,
126  usually plenty. */
127 
128 #define MAX_BUFFER_SIZE 100
129 
130 /* File descriptors for sound device */
131 static int readdev = -1;
132 static int writedev = -1;
133 
134 static int autoanswer = 1;
135 static int mute = 0;
136 static int noaudiocapture = 0;
137 
138 static struct ast_channel *alsa_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
139 static int alsa_digit(struct ast_channel *c, char digit, unsigned int duration);
140 static int alsa_text(struct ast_channel *c, const char *text);
141 static int alsa_hangup(struct ast_channel *c);
142 static int alsa_answer(struct ast_channel *c);
143 static struct ast_frame *alsa_read(struct ast_channel *chan);
144 static int alsa_call(struct ast_channel *c, char *dest, int timeout);
145 static int alsa_write(struct ast_channel *chan, struct ast_frame *f);
146 static int alsa_indicate(struct ast_channel *chan, int cond, const void *data, size_t datalen);
147 static int alsa_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
148 
149 static const struct ast_channel_tech alsa_tech = {
150  .type = "Console",
151  .description = tdesc,
152  .capabilities = AST_FORMAT_SLINEAR,
153  .requester = alsa_request,
154  .send_digit_end = alsa_digit,
155  .send_text = alsa_text,
156  .hangup = alsa_hangup,
157  .answer = alsa_answer,
158  .read = alsa_read,
159  .call = alsa_call,
160  .write = alsa_write,
161  .indicate = alsa_indicate,
162  .fixup = alsa_fixup,
163 };
164 
165 static snd_pcm_t *alsa_card_init(char *dev, snd_pcm_stream_t stream)
166 {
167  int err;
168  int direction;
169  snd_pcm_t *handle = NULL;
170  snd_pcm_hw_params_t *hwparams = NULL;
171  snd_pcm_sw_params_t *swparams = NULL;
172  struct pollfd pfd;
173  snd_pcm_uframes_t period_size = PERIOD_FRAMES * 4;
174  snd_pcm_uframes_t buffer_size = 0;
175  unsigned int rate = DESIRED_RATE;
176  snd_pcm_uframes_t start_threshold, stop_threshold;
177 
178  err = snd_pcm_open(&handle, dev, stream, SND_PCM_NONBLOCK);
179  if (err < 0) {
180  ast_log(LOG_ERROR, "snd_pcm_open failed: %s\n", snd_strerror(err));
181  return NULL;
182  } else {
183  ast_debug(1, "Opening device %s in %s mode\n", dev, (stream == SND_PCM_STREAM_CAPTURE) ? "read" : "write");
184  }
185 
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);
189 
190  err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
191  if (err < 0)
192  ast_log(LOG_ERROR, "set_access failed: %s\n", snd_strerror(err));
193 
194  err = snd_pcm_hw_params_set_format(handle, hwparams, format);
195  if (err < 0)
196  ast_log(LOG_ERROR, "set_format failed: %s\n", snd_strerror(err));
197 
198  err = snd_pcm_hw_params_set_channels(handle, hwparams, 1);
199  if (err < 0)
200  ast_log(LOG_ERROR, "set_channels failed: %s\n", snd_strerror(err));
201 
202  direction = 0;
203  err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &rate, &direction);
204  if (rate != DESIRED_RATE)
205  ast_log(LOG_WARNING, "Rate not correct, requested %d, got %u\n", DESIRED_RATE, rate);
206 
207  direction = 0;
208  err = snd_pcm_hw_params_set_period_size_near(handle, hwparams, &period_size, &direction);
209  if (err < 0)
210  ast_log(LOG_ERROR, "period_size(%lu frames) is bad: %s\n", period_size, snd_strerror(err));
211  else {
212  ast_debug(1, "Period size is %d\n", err);
213  }
214 
215  buffer_size = 4096 * 2; /* period_size * 16; */
216  err = snd_pcm_hw_params_set_buffer_size_near(handle, hwparams, &buffer_size);
217  if (err < 0)
218  ast_log(LOG_WARNING, "Problem setting buffer size of %lu: %s\n", buffer_size, snd_strerror(err));
219  else {
220  ast_debug(1, "Buffer size is set to %d frames\n", err);
221  }
222 
223  err = snd_pcm_hw_params(handle, hwparams);
224  if (err < 0)
225  ast_log(LOG_ERROR, "Couldn't set the new hw params: %s\n", snd_strerror(err));
226 
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);
230 
231  if (stream == SND_PCM_STREAM_PLAYBACK)
232  start_threshold = period_size;
233  else
234  start_threshold = 1;
235 
236  err = snd_pcm_sw_params_set_start_threshold(handle, swparams, start_threshold);
237  if (err < 0)
238  ast_log(LOG_ERROR, "start threshold: %s\n", snd_strerror(err));
239 
240  if (stream == SND_PCM_STREAM_PLAYBACK)
241  stop_threshold = buffer_size;
242  else
243  stop_threshold = buffer_size;
244 
245  err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, stop_threshold);
246  if (err < 0)
247  ast_log(LOG_ERROR, "stop threshold: %s\n", snd_strerror(err));
248 
249  err = snd_pcm_sw_params(handle, swparams);
250  if (err < 0)
251  ast_log(LOG_ERROR, "sw_params: %s\n", snd_strerror(err));
252 
253  err = snd_pcm_poll_descriptors_count(handle);
254  if (err <= 0)
255  ast_log(LOG_ERROR, "Unable to get a poll descriptors count, error is %s\n", snd_strerror(err));
256  if (err != 1) {
257  ast_debug(1, "Can't handle more than one device\n");
258  }
259 
260  snd_pcm_poll_descriptors(handle, &pfd, err);
261  ast_debug(1, "Acquired fd %d from the poll descriptor\n", pfd.fd);
262 
263  if (stream == SND_PCM_STREAM_CAPTURE)
264  readdev = pfd.fd;
265  else
266  writedev = pfd.fd;
267 
268  return handle;
269 }
270 
271 static int soundcard_init(void)
272 {
273  if (!noaudiocapture) {
274  alsa.icard = alsa_card_init(indevname, SND_PCM_STREAM_CAPTURE);
275  if (!alsa.icard) {
276  ast_log(LOG_ERROR, "Problem opening alsa capture device\n");
277  return -1;
278  }
279  }
280 
281  alsa.ocard = alsa_card_init(outdevname, SND_PCM_STREAM_PLAYBACK);
282 
283  if (!alsa.ocard) {
284  ast_log(LOG_ERROR, "Problem opening ALSA playback device\n");
285  return -1;
286  }
287 
288  return writedev;
289 }
290 
291 static int alsa_digit(struct ast_channel *c, char digit, unsigned int duration)
292 {
294  ast_verbose(" << Console Received digit %c of duration %u ms >> \n",
295  digit, duration);
297 
298  return 0;
299 }
300 
301 static int alsa_text(struct ast_channel *c, const char *text)
302 {
304  ast_verbose(" << Console Received text %s >> \n", text);
306 
307  return 0;
308 }
309 
310 static void grab_owner(void)
311 {
312  while (alsa.owner && ast_channel_trylock(alsa.owner)) {
314  }
315 }
316 
317 static int alsa_call(struct ast_channel *c, char *dest, int timeout)
318 {
319  struct ast_frame f = { AST_FRAME_CONTROL };
320 
322  ast_verbose(" << Call placed to '%s' on console >> \n", dest);
323  if (autoanswer) {
324  ast_verbose(" << Auto-answered >> \n");
325  if (mute) {
326  ast_verbose( " << Muted >> \n" );
327  }
328  grab_owner();
329  if (alsa.owner) {
333  }
334  } else {
335  ast_verbose(" << Type 'answer' to answer, or use 'autoanswer' for future calls >> \n");
336  grab_owner();
337  if (alsa.owner) {
342  }
343  }
344  if (!noaudiocapture) {
345  snd_pcm_prepare(alsa.icard);
346  snd_pcm_start(alsa.icard);
347  }
349 
350  return 0;
351 }
352 
353 static int alsa_answer(struct ast_channel *c)
354 {
356  ast_verbose(" << Console call has been answered >> \n");
358  if (!noaudiocapture) {
359  snd_pcm_prepare(alsa.icard);
360  snd_pcm_start(alsa.icard);
361  }
363 
364  return 0;
365 }
366 
367 static int alsa_hangup(struct ast_channel *c)
368 {
370  c->tech_pvt = NULL;
371  alsa.owner = NULL;
372  ast_verbose(" << Hangup on console >> \n");
374  hookstate = 0;
375  if (!noaudiocapture) {
376  snd_pcm_drop(alsa.icard);
377  }
379 
380  return 0;
381 }
382 
383 static int alsa_write(struct ast_channel *chan, struct ast_frame *f)
384 {
385  static char sizbuf[8000];
386  static int sizpos = 0;
387  int len = sizpos;
388  int res = 0;
389  /* size_t frames = 0; */
390  snd_pcm_state_t state;
391 
393 
394  /* We have to digest the frame in 160-byte portions */
395  if (f->datalen > sizeof(sizbuf) - sizpos) {
396  ast_log(LOG_WARNING, "Frame too large\n");
397  res = -1;
398  } else {
399  memcpy(sizbuf + sizpos, f->data.ptr, f->datalen);
400  len += f->datalen;
401  state = snd_pcm_state(alsa.ocard);
402  if (state == SND_PCM_STATE_XRUN)
403  snd_pcm_prepare(alsa.ocard);
404  while ((res = snd_pcm_writei(alsa.ocard, sizbuf, len / 2)) == -EAGAIN) {
405  usleep(1);
406  }
407  if (res == -EPIPE) {
408 #if DEBUG
409  ast_debug(1, "XRUN write\n");
410 #endif
411  snd_pcm_prepare(alsa.ocard);
412  while ((res = snd_pcm_writei(alsa.ocard, sizbuf, len / 2)) == -EAGAIN) {
413  usleep(1);
414  }
415  if (res != len / 2) {
416  ast_log(LOG_ERROR, "Write error: %s\n", snd_strerror(res));
417  res = -1;
418  } else if (res < 0) {
419  ast_log(LOG_ERROR, "Write error %s\n", snd_strerror(res));
420  res = -1;
421  }
422  } else {
423  if (res == -ESTRPIPE)
424  ast_log(LOG_ERROR, "You've got some big problems\n");
425  else if (res < 0)
426  ast_log(LOG_NOTICE, "Error %d on write\n", res);
427  }
428  }
430 
431  return res >= 0 ? 0 : res;
432 }
433 
434 
435 static struct ast_frame *alsa_read(struct ast_channel *chan)
436 {
437  static struct ast_frame f;
438  static short __buf[FRAME_SIZE + AST_FRIENDLY_OFFSET / 2];
439  short *buf;
440  static int readpos = 0;
441  static int left = FRAME_SIZE;
442  snd_pcm_state_t state;
443  int r = 0;
444  int off = 0;
445 
448  f.subclass.integer = 0;
449  f.samples = 0;
450  f.datalen = 0;
451  f.data.ptr = NULL;
452  f.offset = 0;
453  f.src = "Console";
454  f.mallocd = 0;
455  f.delivery.tv_sec = 0;
456  f.delivery.tv_usec = 0;
457 
458  if (noaudiocapture) {
459  /* Return null frame to asterisk*/
461  return &f;
462  }
463 
464  state = snd_pcm_state(alsa.icard);
465  if ((state != SND_PCM_STATE_PREPARED) && (state != SND_PCM_STATE_RUNNING)) {
466  snd_pcm_prepare(alsa.icard);
467  }
468 
469  buf = __buf + AST_FRIENDLY_OFFSET / 2;
470 
471  r = snd_pcm_readi(alsa.icard, buf + readpos, left);
472  if (r == -EPIPE) {
473 #if DEBUG
474  ast_log(LOG_ERROR, "XRUN read\n");
475 #endif
476  snd_pcm_prepare(alsa.icard);
477  } else if (r == -ESTRPIPE) {
478  ast_log(LOG_ERROR, "-ESTRPIPE\n");
479  snd_pcm_prepare(alsa.icard);
480  } else if (r < 0) {
481  ast_log(LOG_ERROR, "Read error: %s\n", snd_strerror(r));
482  } else if (r >= 0) {
483  off -= r;
484  }
485 
486  /* Return NULL frame on error */
487  if (r < 0) {
489  return &f;
490  }
491 
492  /* Update positions */
493  readpos += r;
494  left -= r;
495 
496  if (readpos >= FRAME_SIZE) {
497  /* A real frame */
498  readpos = 0;
499  left = FRAME_SIZE;
500  if (chan->_state != AST_STATE_UP) {
501  /* Don't transmit unless it's up */
503  return &f;
504  }
505  if (mute) {
506  /* Don't transmit if muted */
508  return &f;
509  }
510 
513  f.samples = FRAME_SIZE;
514  f.datalen = FRAME_SIZE * 2;
515  f.data.ptr = buf;
517  f.src = "Console";
518  f.mallocd = 0;
519 
520  }
522 
523  return &f;
524 }
525 
526 static int alsa_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
527 {
528  struct chan_alsa_pvt *p = newchan->tech_pvt;
529 
531  p->owner = newchan;
533 
534  return 0;
535 }
536 
537 static int alsa_indicate(struct ast_channel *chan, int cond, const void *data, size_t datalen)
538 {
539  int res = 0;
540 
542 
543  switch (cond) {
544  case AST_CONTROL_BUSY:
546  case AST_CONTROL_RINGING:
548  case -1:
549  res = -1; /* Ask for inband indications */
550  break;
555  break;
556  case AST_CONTROL_HOLD:
557  ast_verbose(" << Console Has Been Placed on Hold >> \n");
558  ast_moh_start(chan, data, mohinterpret);
559  break;
560  case AST_CONTROL_UNHOLD:
561  ast_verbose(" << Console Has Been Retrieved from Hold >> \n");
562  ast_moh_stop(chan);
563  break;
564  default:
565  ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, chan->name);
566  res = -1;
567  }
568 
570 
571  return res;
572 }
573 
574 static struct ast_channel *alsa_new(struct chan_alsa_pvt *p, int state, const char *linkedid)
575 {
576  struct ast_channel *tmp = NULL;
577 
578  if (!(tmp = ast_channel_alloc(1, state, 0, 0, "", p->exten, p->context, linkedid, 0, "ALSA/%s", indevname)))
579  return NULL;
580 
581  tmp->tech = &alsa_tech;
582  ast_channel_set_fd(tmp, 0, readdev);
586  tmp->tech_pvt = p;
587  if (!ast_strlen_zero(p->context))
588  ast_copy_string(tmp->context, p->context, sizeof(tmp->context));
589  if (!ast_strlen_zero(p->exten))
590  ast_copy_string(tmp->exten, p->exten, sizeof(tmp->exten));
591  if (!ast_strlen_zero(language))
592  ast_string_field_set(tmp, language, language);
593  p->owner = tmp;
596  if (state != AST_STATE_DOWN) {
597  if (ast_pbx_start(tmp)) {
598  ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
599  ast_hangup(tmp);
600  tmp = NULL;
601  }
602  }
603 
604  return tmp;
605 }
606 
607 static struct ast_channel *alsa_request(const char *type, format_t fmt, const struct ast_channel *requestor, void *data, int *cause)
608 {
609  format_t oldformat = fmt;
610  char buf[256];
611  struct ast_channel *tmp = NULL;
612 
613  if (!(fmt &= AST_FORMAT_SLINEAR)) {
614  ast_log(LOG_NOTICE, "Asked to get a channel of format '%s'\n", ast_getformatname_multiple(buf, sizeof(buf), oldformat));
615  return NULL;
616  }
617 
619 
620  if (alsa.owner) {
621  ast_log(LOG_NOTICE, "Already have a call on the ALSA channel\n");
622  *cause = AST_CAUSE_BUSY;
623  } else if (!(tmp = alsa_new(&alsa, AST_STATE_DOWN, requestor ? requestor->linkedid : NULL))) {
624  ast_log(LOG_WARNING, "Unable to create new ALSA channel\n");
625  }
626 
628 
629  return tmp;
630 }
631 
632 static char *autoanswer_complete(const char *line, const char *word, int pos, int state)
633 {
634  switch (state) {
635  case 0:
636  if (!ast_strlen_zero(word) && !strncasecmp(word, "on", MIN(strlen(word), 2)))
637  return ast_strdup("on");
638  case 1:
639  if (!ast_strlen_zero(word) && !strncasecmp(word, "off", MIN(strlen(word), 3)))
640  return ast_strdup("off");
641  default:
642  return NULL;
643  }
644 
645  return NULL;
646 }
647 
648 static char *console_autoanswer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
649 {
650  char *res = CLI_SUCCESS;
651 
652  switch (cmd) {
653  case CLI_INIT:
654  e->command = "console autoanswer";
655  e->usage =
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";
660  return NULL;
661  case CLI_GENERATE:
662  return autoanswer_complete(a->line, a->word, a->pos, a->n);
663  }
664 
665  if ((a->argc != 2) && (a->argc != 3))
666  return CLI_SHOWUSAGE;
667 
669  if (a->argc == 2) {
670  ast_cli(a->fd, "Auto answer is %s.\n", autoanswer ? "on" : "off");
671  } else {
672  if (!strcasecmp(a->argv[2], "on"))
673  autoanswer = -1;
674  else if (!strcasecmp(a->argv[2], "off"))
675  autoanswer = 0;
676  else
677  res = CLI_SHOWUSAGE;
678  }
680 
681  return res;
682 }
683 
684 static char *console_answer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
685 {
686  char *res = CLI_SUCCESS;
687 
688  switch (cmd) {
689  case CLI_INIT:
690  e->command = "console answer";
691  e->usage =
692  "Usage: console answer\n"
693  " Answers an incoming call on the console (ALSA) channel.\n";
694 
695  return NULL;
696  case CLI_GENERATE:
697  return NULL;
698  }
699 
700  if (a->argc != 2)
701  return CLI_SHOWUSAGE;
702 
704 
705  if (!alsa.owner) {
706  ast_cli(a->fd, "No one is calling us\n");
707  res = CLI_FAILURE;
708  } else {
709  if (mute) {
710  ast_verbose( " << Muted >> \n" );
711  }
712  hookstate = 1;
713  grab_owner();
714  if (alsa.owner) {
717  }
718  }
719 
720  if (!noaudiocapture) {
721  snd_pcm_prepare(alsa.icard);
722  snd_pcm_start(alsa.icard);
723  }
724 
726 
727  return res;
728 }
729 
730 static char *console_sendtext(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
731 {
732  int tmparg = 3;
733  char *res = CLI_SUCCESS;
734 
735  switch (cmd) {
736  case CLI_INIT:
737  e->command = "console send text";
738  e->usage =
739  "Usage: console send text <message>\n"
740  " Sends a text message for display on the remote terminal.\n";
741  return NULL;
742  case CLI_GENERATE:
743  return NULL;
744  }
745 
746  if (a->argc < 3)
747  return CLI_SHOWUSAGE;
748 
750 
751  if (!alsa.owner) {
752  ast_cli(a->fd, "No channel active\n");
753  res = CLI_FAILURE;
754  } else {
755  struct ast_frame f = { AST_FRAME_TEXT };
756  char text2send[256] = "";
757 
758  while (tmparg < a->argc) {
759  strncat(text2send, a->argv[tmparg++], sizeof(text2send) - strlen(text2send) - 1);
760  strncat(text2send, " ", sizeof(text2send) - strlen(text2send) - 1);
761  }
762 
763  text2send[strlen(text2send) - 1] = '\n';
764  f.data.ptr = text2send;
765  f.datalen = strlen(text2send) + 1;
766  grab_owner();
767  if (alsa.owner) {
771  }
772  }
773 
775 
776  return res;
777 }
778 
779 static char *console_hangup(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
780 {
781  char *res = CLI_SUCCESS;
782 
783  switch (cmd) {
784  case CLI_INIT:
785  e->command = "console hangup";
786  e->usage =
787  "Usage: console hangup\n"
788  " Hangs up any call currently placed on the console.\n";
789  return NULL;
790  case CLI_GENERATE:
791  return NULL;
792  }
793 
794 
795  if (a->argc != 2)
796  return CLI_SHOWUSAGE;
797 
799 
800  if (!alsa.owner && !hookstate) {
801  ast_cli(a->fd, "No call to hangup\n");
802  res = CLI_FAILURE;
803  } else {
804  hookstate = 0;
805  grab_owner();
806  if (alsa.owner) {
809  }
810  }
811 
813 
814  return res;
815 }
816 
817 static char *console_dial(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
818 {
819  char tmp[256], *tmp2;
820  char *mye, *myc;
821  const char *d;
822  char *res = CLI_SUCCESS;
823 
824  switch (cmd) {
825  case CLI_INIT:
826  e->command = "console dial";
827  e->usage =
828  "Usage: console dial [extension[@context]]\n"
829  " Dials a given extension (and context if specified)\n";
830  return NULL;
831  case CLI_GENERATE:
832  return NULL;
833  }
834 
835  if ((a->argc != 2) && (a->argc != 3))
836  return CLI_SHOWUSAGE;
837 
839 
840  if (alsa.owner) {
841  if (a->argc == 3) {
842  if (alsa.owner) {
843  for (d = a->argv[2]; *d; d++) {
844  struct ast_frame f = { .frametype = AST_FRAME_DTMF, .subclass.integer = *d };
845 
847  }
848  }
849  } else {
850  ast_cli(a->fd, "You're already in a call. You can use this only to dial digits until you hangup\n");
851  res = CLI_FAILURE;
852  }
853  } else {
854  mye = exten;
855  myc = context;
856  if (a->argc == 3) {
857  char *stringp = NULL;
858 
859  ast_copy_string(tmp, a->argv[2], sizeof(tmp));
860  stringp = tmp;
861  strsep(&stringp, "@");
862  tmp2 = strsep(&stringp, "@");
863  if (!ast_strlen_zero(tmp))
864  mye = tmp;
865  if (!ast_strlen_zero(tmp2))
866  myc = tmp2;
867  }
868  if (ast_exists_extension(NULL, myc, mye, 1, NULL)) {
869  ast_copy_string(alsa.exten, mye, sizeof(alsa.exten));
870  ast_copy_string(alsa.context, myc, sizeof(alsa.context));
871  hookstate = 1;
873  } else
874  ast_cli(a->fd, "No such extension '%s' in context '%s'\n", mye, myc);
875  }
876 
878 
879  return res;
880 }
881 
882 static char *console_mute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
883 {
884  int toggle = 0;
885  char *res = CLI_SUCCESS;
886 
887  switch (cmd) {
888  case CLI_INIT:
889  e->command = "console {mute|unmute} [toggle]";
890  e->usage =
891  "Usage: console {mute|unmute} [toggle]\n"
892  " Mute/unmute the microphone.\n";
893  return NULL;
894  case CLI_GENERATE:
895  return NULL;
896  }
897 
898 
899  if (a->argc > 3) {
900  return CLI_SHOWUSAGE;
901  }
902 
903  if (a->argc == 3) {
904  if (strcasecmp(a->argv[2], "toggle"))
905  return CLI_SHOWUSAGE;
906  toggle = 1;
907  }
908 
909  if (a->argc < 2) {
910  return CLI_SHOWUSAGE;
911  }
912 
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;
917  } else {
918  return CLI_SHOWUSAGE;
919  }
920 
921  ast_cli(a->fd, "Console mic is %s\n", mute ? "off" : "on");
922 
923  return res;
924 }
925 
926 static struct ast_cli_entry cli_alsa[] = {
927  AST_CLI_DEFINE(console_answer, "Answer an incoming console call"),
928  AST_CLI_DEFINE(console_hangup, "Hangup a call on the console"),
929  AST_CLI_DEFINE(console_dial, "Dial an extension on the console"),
930  AST_CLI_DEFINE(console_sendtext, "Send text to the remote device"),
931  AST_CLI_DEFINE(console_autoanswer, "Sets/displays autoanswer"),
932  AST_CLI_DEFINE(console_mute, "Disable/Enable mic input"),
933 };
934 
935 static int load_module(void)
936 {
937  struct ast_config *cfg;
938  struct ast_variable *v;
939  struct ast_flags config_flags = { 0 };
940 
941  /* Copy the default jb config over global_jbconf */
942  memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
943 
944  strcpy(mohinterpret, "default");
945 
946  if (!(cfg = ast_config_load(config, config_flags))) {
947  ast_log(LOG_ERROR, "Unable to read ALSA configuration file %s. Aborting.\n", config);
949  } else if (cfg == CONFIG_STATUS_FILEINVALID) {
950  ast_log(LOG_ERROR, "%s is in an invalid format. Aborting.\n", config);
952  }
953 
954  v = ast_variable_browse(cfg, "general");
955  for (; v; v = v->next) {
956  /* handle jb conf */
957  if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) {
958  continue;
959  }
960 
961  if (!strcasecmp(v->name, "autoanswer")) {
962  autoanswer = ast_true(v->value);
963  } else if (!strcasecmp(v->name, "mute")) {
964  mute = ast_true(v->value);
965  } else if (!strcasecmp(v->name, "noaudiocapture")) {
966  noaudiocapture = ast_true(v->value);
967  } else if (!strcasecmp(v->name, "silencesuppression")) {
968  silencesuppression = ast_true(v->value);
969  } else if (!strcasecmp(v->name, "silencethreshold")) {
970  silencethreshold = atoi(v->value);
971  } else if (!strcasecmp(v->name, "context")) {
972  ast_copy_string(context, v->value, sizeof(context));
973  } else if (!strcasecmp(v->name, "language")) {
974  ast_copy_string(language, v->value, sizeof(language));
975  } else if (!strcasecmp(v->name, "extension")) {
976  ast_copy_string(exten, v->value, sizeof(exten));
977  } else if (!strcasecmp(v->name, "input_device")) {
978  ast_copy_string(indevname, v->value, sizeof(indevname));
979  } else if (!strcasecmp(v->name, "output_device")) {
980  ast_copy_string(outdevname, v->value, sizeof(outdevname));
981  } else if (!strcasecmp(v->name, "mohinterpret")) {
982  ast_copy_string(mohinterpret, v->value, sizeof(mohinterpret));
983  }
984  }
985  ast_config_destroy(cfg);
986 
987  if (soundcard_init() < 0) {
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");
991  }
992 
993  if (ast_channel_register(&alsa_tech)) {
994  ast_log(LOG_ERROR, "Unable to register channel class 'Console'\n");
996  }
997 
998  ast_cli_register_multiple(cli_alsa, ARRAY_LEN(cli_alsa));
999 
1000  return AST_MODULE_LOAD_SUCCESS;
1001 }
1002 
1003 static int unload_module(void)
1004 {
1005  ast_channel_unregister(&alsa_tech);
1006  ast_cli_unregister_multiple(cli_alsa, ARRAY_LEN(cli_alsa));
1007 
1008  if (alsa.icard)
1009  snd_pcm_close(alsa.icard);
1010  if (alsa.ocard)
1011  snd_pcm_close(alsa.ocard);
1012  if (alsa.owner)
1014  if (alsa.owner)
1015  return -1;
1016 
1017  return 0;
1018 }
1019 
1020 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "ALSA Console Channel Driver",
1021  .load = load_module,
1022  .unload = unload_module,
1023  .load_pri = AST_MODPRI_CHANNEL_DRIVER,
1024  );
static char * console_dial(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_alsa.c:817
union ast_frame_subclass subclass
Definition: frame.h:146
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2804
struct ast_channel * owner
Definition: chan_alsa.c:117
enum sip_cc_notify_state state
Definition: chan_sip.c:842
static char mohinterpret[MAX_MUSICCLASS]
Definition: chan_alsa.c:110
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
#define FRAME_SIZE
Definition: chan_alsa.c:79
Main Channel structure associated with a channel.
Definition: channel.h:742
Music on hold handling.
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:191
const char *const type
Definition: channel.h:508
Asterisk main include file. File version handling, generic pbx functions.
#define ALSA_OUTDEV
Definition: chan_alsa.c:75
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static const char tdesc[]
Definition: chan_alsa.c:104
int offset
Definition: frame.h:156
void ast_module_unref(struct ast_module *)
Definition: loader.c:1312
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame with payload.
Definition: channel.c:1601
char * strsep(char **str, const char *delims)
static struct ast_channel_tech alsa_tech
Definition: chan_alsa.c:149
snd_pcm_t * icard
Definition: chan_alsa.c:120
snd_pcm_t * ocard
Definition: chan_alsa.c:120
#define ast_strdup(a)
Definition: astmm.h:109
format_t writeformat
Definition: channel.h:854
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: utils.h:653
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: cli.c:2177
static int silencethreshold
Definition: chan_alsa.c:100
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4393
#define MAX_MUSICCLASS
Definition: channel.h:139
static struct ast_channel * alsa_new(struct chan_alsa_pvt *p, int state, const char *linkedid)
Definition: chan_alsa.c:574
static struct chan_alsa_pvt alsa
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
Definition: channel.c:938
void * ptr
Definition: frame.h:160
void * tech_pvt
Definition: channel.h:744
static int alsa_write(struct ast_channel *chan, struct ast_frame *f)
Definition: chan_alsa.c:383
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
#define DEADLOCK_AVOIDANCE(lock)
Definition: lock.h:485
descriptor for a cli entry.
Definition: cli.h:165
const int argc
Definition: cli.h:154
#define LOG_WARNING
Definition: logger.h:144
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:5879
#define DESIRED_RATE
Definition: chan_alsa.c:76
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
Definition: config.c:597
int ast_jb_read_conf(struct ast_jb_conf *conf, const char *varname, const char *value)
Sets jitterbuffer configuration property.
Definition: abstract_jb.c:577
void ast_verbose(const char *fmt,...)
Definition: logger.c:1568
#define AST_FRAME_DTMF
Definition: frame.h:128
static struct ast_jb_conf global_jbconf
Definition: chan_alsa.c:70
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
static int noaudiocapture
Definition: chan_alsa.c:136
static int alsa_text(struct ast_channel *c, const char *text)
Definition: chan_alsa.c:301
static int autoanswer
Definition: chan_alsa.c:134
static int alsa_digit(struct ast_channel *c, char digit, unsigned int duration)
Definition: chan_alsa.c:291
Definition: cli.h:146
Configuration File Parser.
static char * console_sendtext(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_alsa.c:730
#define ast_mutex_lock(a)
Definition: lock.h:155
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 ...
Definition: channel.c:907
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:374
char * text
Definition: app_queue.c:1091
format_t nativeformats
Definition: channel.h:852
static char * console_autoanswer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_alsa.c:648
format_t codec
Definition: frame.h:137
const char * data
Definition: channel.h:755
static int alsa_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
Definition: chan_alsa.c:526
Common implementation-independent jitterbuffer stuff.
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
const ast_string_field linkedid
Definition: channel.h:787
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:8051
#define ast_verb(level,...)
Definition: logger.h:243
Definition: ael.tab.c:203
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
static int writedev
Definition: chan_alsa.c:132
const char * line
Definition: cli.h:156
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,...)
Definition: channel.c:9825
static int alsa_indicate(struct ast_channel *chan, int cond, const void *data, size_t datalen)
Definition: chan_alsa.c:537
#define MAX_LANGUAGE
Definition: channel.h:138
static int mute
Definition: chan_alsa.c:135
String fields in structures.
Utility functions.
int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
Queue a hangup frame with hangupcause set.
Definition: channel.c:1581
#define MIN(a, b)
Definition: utils.h:226
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
const char * value
Definition: config.h:79
struct ast_module * self
Definition: module.h:227
General Asterisk PBX channel definitions.
#define AST_FRIENDLY_OFFSET
Offset into a frame&#39;s data buffer.
Definition: frame.h:204
const char * src
Definition: frame.h:158
const int fd
Definition: cli.h:153
#define ast_config_load(filename, flags)
Load a config file.
Definition: config.h:170
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
const int n
Definition: cli.h:159
Asterisk internal frame definitions.
Asterisk architecture endianess compatibility definitions.
ast_cond_t cond
Definition: app_meetme.c:963
#define AST_MAX_EXTENSION
Definition: channel.h:135
int datalen
Definition: frame.h:148
#define AST_CAUSE_NORMAL_CLEARING
Definition: causes.h:105
static int load_module(void)
Definition: chan_alsa.c:935
int ast_softhangup(struct ast_channel *chan, int reason)
Softly hangup up a channel.
Definition: channel.c:2746
static int soundcard_init(void)
Definition: chan_alsa.c:271
static char language[MAX_LANGUAGE]
Definition: chan_alsa.c:108
const char * name
Definition: config.h:77
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:5400
Structure to describe a channel &quot;technology&quot;, ie a channel driver See for examples: ...
Definition: channel.h:507
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&#39;s frame queue.
Definition: channel.c:1558
const char *const * argv
Definition: cli.h:155
static int alsa_call(struct ast_channel *c, char *dest, int timeout)
Definition: chan_alsa.c:317
#define LOG_ERROR
Definition: logger.h:155
static char outdevname[50]
Definition: chan_alsa.c:97
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
int64_t format_t
Definition: frame_defs.h:32
#define CLI_SHOWUSAGE
Definition: cli.h:44
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
enum ast_channel_state _state
Definition: channel.h:839
const ast_string_field name
Definition: channel.h:787
static ast_mutex_t alsalock
Definition: chan_alsa.c:102
char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:119
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
Definition: channel.c:8040
char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
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...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
static char indevname[50]
Definition: chan_alsa.c:96
#define ast_channel_unlock(chan)
Definition: channel.h:2467
#define CLI_FAILURE
Definition: cli.h:45
static struct ast_cli_entry cli_alsa[]
Definition: chan_alsa.c:926
#define AST_MAX_CONTEXT
Definition: channel.h:136
char * command
Definition: cli.h:180
static struct ast_format f[]
Definition: format_g726.c:181
const char * word
Definition: cli.h:157
#define PERIOD_FRAMES
Definition: chan_alsa.c:80
unsigned int flags
Combination of the AST_JB_ENABLED, AST_JB_FORCED and AST_JB_LOG flags.
Definition: abstract_jb.h:58
static char * console_hangup(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_alsa.c:779
static const char type[]
Definition: chan_nbs.c:57
Structure used to handle boolean flags.
Definition: utils.h:200
static struct ast_frame * alsa_read(struct ast_channel *chan)
Definition: chan_alsa.c:435
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
Definition: channel.c:2631
struct timeval delivery
Definition: frame.h:162
void ast_jb_configure(struct ast_channel *chan, const struct ast_jb_conf *conf)
Configures a jitterbuffer on a channel.
Definition: abstract_jb.c:616
int mallocd
Definition: frame.h:152
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
static char * console_mute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_alsa.c:882
static void grab_owner(void)
Definition: chan_alsa.c:310
static char * autoanswer_complete(const char *line, const char *word, int pos, int state)
Definition: chan_alsa.c:632
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
Standard Command Line Interface.
format_t readformat
Definition: channel.h:853
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
Definition: cli.c:2167
const int pos
Definition: cli.h:158
static snd_pcm_t * alsa_card_init(char *dev, snd_pcm_stream_t stream)
Definition: chan_alsa.c:165
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7119
static int hookstate
Definition: chan_alsa.c:112
#define AST_CAUSE_BUSY
Definition: causes.h:148
char * ast_getformatname_multiple(char *buf, size_t size, format_t format)
Get the names of a set of formats.
Definition: frame.c:591
Data structure associated with a single frame of data.
Definition: frame.h:142
Internal Asterisk hangup causes.
static const char config[]
Definition: chan_alsa.c:105
enum ast_frame_type frametype
Definition: frame.h:144
struct ast_variable * next
Definition: config.h:82
#define ast_channel_trylock(chan)
Definition: channel.h:2468
static char * console_answer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_alsa.c:684
#define CONFIG_STATUS_FILEINVALID
Definition: config.h:52
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:38
Asterisk module definitions.
static int alsa_answer(struct ast_channel *c)
Definition: chan_alsa.c:353
static snd_pcm_format_t format
Definition: chan_alsa.c:93
union ast_frame::@172 data
struct ast_channel_tech * tech
Definition: channel.h:743
static int readdev
Definition: chan_alsa.c:131
General jitterbuffer configuration.
Definition: abstract_jb.h:55
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:526
static struct ast_channel * alsa_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
Definition: chan_alsa.c:607
static struct ast_jb_conf default_jbconf
Definition: chan_alsa.c:63
static int silencesuppression
Definition: chan_alsa.c:99
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180
int samples
Definition: frame.h:150
static int unload_module(void)
Definition: chan_alsa.c:1003
#define ast_mutex_unlock(a)
Definition: lock.h:156
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:344
struct ast_module * ast_module_ref(struct ast_module *)
Definition: loader.c:1300
static int alsa_hangup(struct ast_channel *c)
Definition: chan_alsa.c:367
#define ALSA_INDEV
Definition: chan_alsa.c:74