Asterisk - The Open Source Telephony Project  18.5.0
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 <[email protected]>
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 <[email protected]>
23  *
24  * \ingroup channel_drivers
25  */
26 
27 /*! \li \ref chan_alsa.c uses the configuration file \ref alsa.conf
28  * \addtogroup configuration_file
29  */
30 
31 /*! \page alsa.conf alsa.conf
32  * \verbinclude alsa.conf.sample
33  */
34 
35 /*** MODULEINFO
36  <depend>alsa</depend>
37  <support_level>extended</support_level>
38  ***/
39 
40 #include "asterisk.h"
41 
42 #include <errno.h>
43 #ifndef ESTRPIPE
44 #define ESTRPIPE EPIPE
45 #endif
46 #include <fcntl.h>
47 #include <sys/ioctl.h>
48 #include <sys/time.h>
49 
50 #define ALSA_PCM_NEW_HW_PARAMS_API
51 #define ALSA_PCM_NEW_SW_PARAMS_API
52 #include <alsa/asoundlib.h>
53 
54 #include "asterisk/frame.h"
55 #include "asterisk/channel.h"
56 #include "asterisk/module.h"
57 #include "asterisk/pbx.h"
58 #include "asterisk/config.h"
59 #include "asterisk/cli.h"
60 #include "asterisk/utils.h"
61 #include "asterisk/causes.h"
62 #include "asterisk/endian.h"
63 #include "asterisk/stringfields.h"
64 #include "asterisk/abstract_jb.h"
65 #include "asterisk/musiconhold.h"
66 #include "asterisk/poll-compat.h"
68 #include "asterisk/format_cache.h"
69 
70 /*! Global jitterbuffer configuration - by default, jb is disabled
71  * \note Values shown here match the defaults shown in alsa.conf.sample */
72 static struct ast_jb_conf default_jbconf = {
73  .flags = 0,
74  .max_size = 200,
75  .resync_threshold = 1000,
76  .impl = "fixed",
77  .target_extra = 40,
78 };
79 static struct ast_jb_conf global_jbconf;
80 
81 #define DEBUG 0
82 /* Which device to use */
83 #define ALSA_INDEV "default"
84 #define ALSA_OUTDEV "default"
85 #define DESIRED_RATE 8000
86 
87 /* Lets use 160 sample frames, just like GSM. */
88 #define FRAME_SIZE 160
89 #define PERIOD_FRAMES 80 /* 80 Frames, at 2 bytes each */
90 
91 /* When you set the frame size, you have to come up with
92  the right buffer format as well. */
93 /* 5 64-byte frames = one frame */
94 #define BUFFER_FMT ((buffersize * 10) << 16) | (0x0006);
95 
96 /* Don't switch between read/write modes faster than every 300 ms */
97 #define MIN_SWITCH_TIME 600
98 
99 #if __BYTE_ORDER == __LITTLE_ENDIAN
100 static snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
101 #else
102 static snd_pcm_format_t format = SND_PCM_FORMAT_S16_BE;
103 #endif
104 
105 static char indevname[50] = ALSA_INDEV;
106 static char outdevname[50] = ALSA_OUTDEV;
107 
108 static int silencesuppression = 0;
109 static int silencethreshold = 1000;
110 
112 
113 static const char tdesc[] = "ALSA Console Channel Driver";
114 static const char config[] = "alsa.conf";
115 
116 static char context[AST_MAX_CONTEXT] = "default";
117 static char language[MAX_LANGUAGE] = "";
118 static char exten[AST_MAX_EXTENSION] = "s";
120 
121 static int hookstate = 0;
122 
123 static struct chan_alsa_pvt {
124  /* We only have one ALSA structure -- near sighted perhaps, but it
125  keeps this driver as simple as possible -- as it should be. */
129  snd_pcm_t *icard, *ocard;
130 
131 } alsa;
132 
133 /* Number of buffers... Each is FRAMESIZE/8 ms long. For example
134  with 160 sample frames, and a buffer size of 3, we have a 60ms buffer,
135  usually plenty. */
136 
137 #define MAX_BUFFER_SIZE 100
138 
139 /* File descriptors for sound device */
140 static int readdev = -1;
141 static int writedev = -1;
142 
143 static int autoanswer = 1;
144 static int mute = 0;
145 static int noaudiocapture = 0;
146 
147 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);
148 static int alsa_digit(struct ast_channel *c, char digit, unsigned int duration);
149 static int alsa_text(struct ast_channel *c, const char *text);
150 static int alsa_hangup(struct ast_channel *c);
151 static int alsa_answer(struct ast_channel *c);
152 static struct ast_frame *alsa_read(struct ast_channel *chan);
153 static int alsa_call(struct ast_channel *c, const char *dest, int timeout);
154 static int alsa_write(struct ast_channel *chan, struct ast_frame *f);
155 static int alsa_indicate(struct ast_channel *chan, int cond, const void *data, size_t datalen);
156 static int alsa_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
157 
158 static struct ast_channel_tech alsa_tech = {
159  .type = "Console",
160  .description = tdesc,
161  .requester = alsa_request,
162  .send_digit_end = alsa_digit,
163  .send_text = alsa_text,
164  .hangup = alsa_hangup,
165  .answer = alsa_answer,
166  .read = alsa_read,
167  .call = alsa_call,
168  .write = alsa_write,
169  .indicate = alsa_indicate,
170  .fixup = alsa_fixup,
171 };
172 
173 static snd_pcm_t *alsa_card_init(char *dev, snd_pcm_stream_t stream)
174 {
175  int err;
176  int direction;
177  snd_pcm_t *handle = NULL;
178  snd_pcm_hw_params_t *hwparams = NULL;
179  snd_pcm_sw_params_t *swparams = NULL;
180  struct pollfd pfd;
181  snd_pcm_uframes_t period_size = PERIOD_FRAMES * 4;
182  snd_pcm_uframes_t buffer_size = 0;
183  unsigned int rate = DESIRED_RATE;
184  snd_pcm_uframes_t start_threshold, stop_threshold;
185 
186  err = snd_pcm_open(&handle, dev, stream, SND_PCM_NONBLOCK);
187  if (err < 0) {
188  ast_log(LOG_ERROR, "snd_pcm_open failed: %s\n", snd_strerror(err));
189  return NULL;
190  } else {
191  ast_debug(1, "Opening device %s in %s mode\n", dev, (stream == SND_PCM_STREAM_CAPTURE) ? "read" : "write");
192  }
193 
194  hwparams = ast_alloca(snd_pcm_hw_params_sizeof());
195  memset(hwparams, 0, snd_pcm_hw_params_sizeof());
196  snd_pcm_hw_params_any(handle, hwparams);
197 
198  err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
199  if (err < 0)
200  ast_log(LOG_ERROR, "set_access failed: %s\n", snd_strerror(err));
201 
202  err = snd_pcm_hw_params_set_format(handle, hwparams, format);
203  if (err < 0)
204  ast_log(LOG_ERROR, "set_format failed: %s\n", snd_strerror(err));
205 
206  err = snd_pcm_hw_params_set_channels(handle, hwparams, 1);
207  if (err < 0)
208  ast_log(LOG_ERROR, "set_channels failed: %s\n", snd_strerror(err));
209 
210  direction = 0;
211  err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &rate, &direction);
212  if (rate != DESIRED_RATE)
213  ast_log(LOG_WARNING, "Rate not correct, requested %d, got %u\n", DESIRED_RATE, rate);
214 
215  direction = 0;
216  err = snd_pcm_hw_params_set_period_size_near(handle, hwparams, &period_size, &direction);
217  if (err < 0)
218  ast_log(LOG_ERROR, "period_size(%lu frames) is bad: %s\n", period_size, snd_strerror(err));
219  else {
220  ast_debug(1, "Period size is %d\n", err);
221  }
222 
223  buffer_size = 4096 * 2; /* period_size * 16; */
224  err = snd_pcm_hw_params_set_buffer_size_near(handle, hwparams, &buffer_size);
225  if (err < 0)
226  ast_log(LOG_WARNING, "Problem setting buffer size of %lu: %s\n", buffer_size, snd_strerror(err));
227  else {
228  ast_debug(1, "Buffer size is set to %d frames\n", err);
229  }
230 
231  err = snd_pcm_hw_params(handle, hwparams);
232  if (err < 0)
233  ast_log(LOG_ERROR, "Couldn't set the new hw params: %s\n", snd_strerror(err));
234 
235  swparams = ast_alloca(snd_pcm_sw_params_sizeof());
236  memset(swparams, 0, snd_pcm_sw_params_sizeof());
237  snd_pcm_sw_params_current(handle, swparams);
238 
239  if (stream == SND_PCM_STREAM_PLAYBACK)
240  start_threshold = period_size;
241  else
242  start_threshold = 1;
243 
244  err = snd_pcm_sw_params_set_start_threshold(handle, swparams, start_threshold);
245  if (err < 0)
246  ast_log(LOG_ERROR, "start threshold: %s\n", snd_strerror(err));
247 
248  if (stream == SND_PCM_STREAM_PLAYBACK)
249  stop_threshold = buffer_size;
250  else
251  stop_threshold = buffer_size;
252 
253  err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, stop_threshold);
254  if (err < 0)
255  ast_log(LOG_ERROR, "stop threshold: %s\n", snd_strerror(err));
256 
257  err = snd_pcm_sw_params(handle, swparams);
258  if (err < 0)
259  ast_log(LOG_ERROR, "sw_params: %s\n", snd_strerror(err));
260 
261  err = snd_pcm_poll_descriptors_count(handle);
262  if (err <= 0)
263  ast_log(LOG_ERROR, "Unable to get a poll descriptors count, error is %s\n", snd_strerror(err));
264  if (err != 1) {
265  ast_debug(1, "Can't handle more than one device\n");
266  }
267 
268  snd_pcm_poll_descriptors(handle, &pfd, err);
269  ast_debug(1, "Acquired fd %d from the poll descriptor\n", pfd.fd);
270 
271  if (stream == SND_PCM_STREAM_CAPTURE)
272  readdev = pfd.fd;
273  else
274  writedev = pfd.fd;
275 
276  return handle;
277 }
278 
279 static int soundcard_init(void)
280 {
281  if (!noaudiocapture) {
282  alsa.icard = alsa_card_init(indevname, SND_PCM_STREAM_CAPTURE);
283  if (!alsa.icard) {
284  ast_log(LOG_ERROR, "Problem opening alsa capture device\n");
285  return -1;
286  }
287  }
288 
289  alsa.ocard = alsa_card_init(outdevname, SND_PCM_STREAM_PLAYBACK);
290 
291  if (!alsa.ocard) {
292  ast_log(LOG_ERROR, "Problem opening ALSA playback device\n");
293  return -1;
294  }
295 
296  return writedev;
297 }
298 
299 static int alsa_digit(struct ast_channel *c, char digit, unsigned int duration)
300 {
302  ast_verbose(" << Console Received digit %c of duration %u ms >> \n",
303  digit, duration);
305 
306  return 0;
307 }
308 
309 static int alsa_text(struct ast_channel *c, const char *text)
310 {
312  ast_verbose(" << Console Received text %s >> \n", text);
314 
315  return 0;
316 }
317 
318 static void grab_owner(void)
319 {
320  while (alsa.owner && ast_channel_trylock(alsa.owner)) {
322  }
323 }
324 
325 static int alsa_call(struct ast_channel *c, const char *dest, int timeout)
326 {
327  struct ast_frame f = { AST_FRAME_CONTROL };
328 
330  ast_verbose(" << Call placed to '%s' on console >> \n", dest);
331  if (autoanswer) {
332  ast_verbose(" << Auto-answered >> \n");
333  if (mute) {
334  ast_verbose( " << Muted >> \n" );
335  }
336  grab_owner();
337  if (alsa.owner) {
341  }
342  } else {
343  ast_verbose(" << Type 'answer' to answer, or use 'autoanswer' for future calls >> \n");
344  grab_owner();
345  if (alsa.owner) {
350  }
351  }
352  if (!noaudiocapture) {
353  snd_pcm_prepare(alsa.icard);
354  snd_pcm_start(alsa.icard);
355  }
357 
358  return 0;
359 }
360 
361 static int alsa_answer(struct ast_channel *c)
362 {
364  ast_verbose(" << Console call has been answered >> \n");
366  if (!noaudiocapture) {
367  snd_pcm_prepare(alsa.icard);
368  snd_pcm_start(alsa.icard);
369  }
371 
372  return 0;
373 }
374 
375 static int alsa_hangup(struct ast_channel *c)
376 {
379  alsa.owner = NULL;
380  ast_verbose(" << Hangup on console >> \n");
382  hookstate = 0;
383  if (!noaudiocapture) {
384  snd_pcm_drop(alsa.icard);
385  }
387 
388  return 0;
389 }
390 
391 static int alsa_write(struct ast_channel *chan, struct ast_frame *f)
392 {
393  static char sizbuf[8000];
394  static int sizpos = 0;
395  int len = sizpos;
396  int res = 0;
397  /* size_t frames = 0; */
398  snd_pcm_state_t state;
399 
401 
402  /* We have to digest the frame in 160-byte portions */
403  if (f->datalen > sizeof(sizbuf) - sizpos) {
404  ast_log(LOG_WARNING, "Frame too large\n");
405  res = -1;
406  } else {
407  memcpy(sizbuf + sizpos, f->data.ptr, f->datalen);
408  len += f->datalen;
409  state = snd_pcm_state(alsa.ocard);
410  if (state == SND_PCM_STATE_XRUN)
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 == -EPIPE) {
416 #if DEBUG
417  ast_debug(1, "XRUN write\n");
418 #endif
419  snd_pcm_prepare(alsa.ocard);
420  while ((res = snd_pcm_writei(alsa.ocard, sizbuf, len / 2)) == -EAGAIN) {
421  usleep(1);
422  }
423  if (res != len / 2) {
424  ast_log(LOG_ERROR, "Write error: %s\n", snd_strerror(res));
425  res = -1;
426  } else if (res < 0) {
427  ast_log(LOG_ERROR, "Write error %s\n", snd_strerror(res));
428  res = -1;
429  }
430  } else {
431  if (res == -ESTRPIPE)
432  ast_log(LOG_ERROR, "You've got some big problems\n");
433  else if (res < 0)
434  ast_log(LOG_NOTICE, "Error %d on write\n", res);
435  }
436  }
438 
439  return res >= 0 ? 0 : res;
440 }
441 
442 
443 static struct ast_frame *alsa_read(struct ast_channel *chan)
444 {
445  static struct ast_frame f;
446  static short __buf[FRAME_SIZE + AST_FRIENDLY_OFFSET / 2];
447  short *buf;
448  static int readpos = 0;
449  static int left = FRAME_SIZE;
450  snd_pcm_state_t state;
451  int r = 0;
452 
455  f.subclass.integer = 0;
456  f.samples = 0;
457  f.datalen = 0;
458  f.data.ptr = NULL;
459  f.offset = 0;
460  f.src = "Console";
461  f.mallocd = 0;
462  f.delivery.tv_sec = 0;
463  f.delivery.tv_usec = 0;
464 
465  if (noaudiocapture) {
466  /* Return null frame to asterisk*/
468  return &f;
469  }
470 
471  state = snd_pcm_state(alsa.icard);
472  if ((state != SND_PCM_STATE_PREPARED) && (state != SND_PCM_STATE_RUNNING)) {
473  snd_pcm_prepare(alsa.icard);
474  }
475 
476  buf = __buf + AST_FRIENDLY_OFFSET / 2;
477 
478  r = snd_pcm_readi(alsa.icard, buf + readpos, left);
479  if (r == -EPIPE) {
480 #if DEBUG
481  ast_log(LOG_ERROR, "XRUN read\n");
482 #endif
483  snd_pcm_prepare(alsa.icard);
484  } else if (r == -ESTRPIPE) {
485  ast_log(LOG_ERROR, "-ESTRPIPE\n");
486  snd_pcm_prepare(alsa.icard);
487  } else if (r < 0) {
488  ast_log(LOG_ERROR, "Read error: %s\n", snd_strerror(r));
489  }
490 
491  /* Return NULL frame on error */
492  if (r < 0) {
494  return &f;
495  }
496 
497  /* Update positions */
498  readpos += r;
499  left -= r;
500 
501  if (readpos >= FRAME_SIZE) {
502  /* A real frame */
503  readpos = 0;
504  left = FRAME_SIZE;
505  if (ast_channel_state(chan) != AST_STATE_UP) {
506  /* Don't transmit unless it's up */
508  return &f;
509  }
510  if (mute) {
511  /* Don't transmit if muted */
513  return &f;
514  }
515 
518  f.samples = FRAME_SIZE;
519  f.datalen = FRAME_SIZE * 2;
520  f.data.ptr = buf;
522  f.src = "Console";
523  f.mallocd = 0;
524 
525  }
527 
528  return &f;
529 }
530 
531 static int alsa_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
532 {
533  struct chan_alsa_pvt *p = ast_channel_tech_pvt(newchan);
534 
536  p->owner = newchan;
538 
539  return 0;
540 }
541 
542 static int alsa_indicate(struct ast_channel *chan, int cond, const void *data, size_t datalen)
543 {
544  int res = 0;
545 
547 
548  switch (cond) {
549  case AST_CONTROL_BUSY:
551  case AST_CONTROL_RINGING:
554  case -1:
555  res = -1; /* Ask for inband indications */
556  break;
561  break;
562  case AST_CONTROL_HOLD:
563  ast_verbose(" << Console Has Been Placed on Hold >> \n");
564  ast_moh_start(chan, data, mohinterpret);
565  break;
566  case AST_CONTROL_UNHOLD:
567  ast_verbose(" << Console Has Been Retrieved from Hold >> \n");
568  ast_moh_stop(chan);
569  break;
570  default:
571  ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, ast_channel_name(chan));
572  res = -1;
573  }
574 
576 
577  return res;
578 }
579 
580 static struct ast_channel *alsa_new(struct chan_alsa_pvt *p, int state, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
581 {
582  struct ast_channel *tmp = NULL;
583 
584  if (!(tmp = ast_channel_alloc(1, state, 0, 0, "", p->exten, p->context, assignedids, requestor, 0, "ALSA/%s", indevname)))
585  return NULL;
586 
588 
589  ast_channel_tech_set(tmp, &alsa_tech);
590  ast_channel_set_fd(tmp, 0, readdev);
594 
595  ast_channel_tech_pvt_set(tmp, p);
596  if (!ast_strlen_zero(p->context))
598  if (!ast_strlen_zero(p->exten))
599  ast_channel_exten_set(tmp, p->exten);
601  ast_channel_language_set(tmp, language);
602  p->owner = tmp;
605 
607  ast_channel_unlock(tmp);
608 
609  if (state != AST_STATE_DOWN) {
610  if (ast_pbx_start(tmp)) {
611  ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
612  ast_hangup(tmp);
613  tmp = NULL;
614  }
615  }
616 
617  return tmp;
618 }
619 
620 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)
621 {
622  struct ast_channel *tmp = NULL;
623 
625  struct ast_str *codec_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
626  ast_log(LOG_NOTICE, "Asked to get a channel of format '%s'\n", ast_format_cap_get_names(cap, &codec_buf));
627  return NULL;
628  }
629 
631 
632  if (alsa.owner) {
633  ast_log(LOG_NOTICE, "Already have a call on the ALSA channel\n");
634  *cause = AST_CAUSE_BUSY;
635  } else if (!(tmp = alsa_new(&alsa, AST_STATE_DOWN, assignedids, requestor))) {
636  ast_log(LOG_WARNING, "Unable to create new ALSA channel\n");
637  }
638 
640 
641  return tmp;
642 }
643 
644 static char *console_autoanswer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
645 {
646  char *res = CLI_SUCCESS;
647 
648  switch (cmd) {
649  case CLI_INIT:
650  e->command = "console autoanswer [on|off]";
651  e->usage =
652  "Usage: console autoanswer [on|off]\n"
653  " Enables or disables autoanswer feature. If used without\n"
654  " argument, displays the current on/off status of autoanswer.\n"
655  " The default value of autoanswer is in 'alsa.conf'.\n";
656  return NULL;
657  case CLI_GENERATE:
658  return NULL;
659  }
660 
661  if ((a->argc != 2) && (a->argc != 3))
662  return CLI_SHOWUSAGE;
663 
665  if (a->argc == 2) {
666  ast_cli(a->fd, "Auto answer is %s.\n", autoanswer ? "on" : "off");
667  } else {
668  if (!strcasecmp(a->argv[2], "on"))
669  autoanswer = -1;
670  else if (!strcasecmp(a->argv[2], "off"))
671  autoanswer = 0;
672  else
673  res = CLI_SHOWUSAGE;
674  }
676 
677  return res;
678 }
679 
680 static char *console_answer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
681 {
682  char *res = CLI_SUCCESS;
683 
684  switch (cmd) {
685  case CLI_INIT:
686  e->command = "console answer";
687  e->usage =
688  "Usage: console answer\n"
689  " Answers an incoming call on the console (ALSA) channel.\n";
690 
691  return NULL;
692  case CLI_GENERATE:
693  return NULL;
694  }
695 
696  if (a->argc != 2)
697  return CLI_SHOWUSAGE;
698 
700 
701  if (!alsa.owner) {
702  ast_cli(a->fd, "No one is calling us\n");
703  res = CLI_FAILURE;
704  } else {
705  if (mute) {
706  ast_verbose( " << Muted >> \n" );
707  }
708  hookstate = 1;
709  grab_owner();
710  if (alsa.owner) {
713  }
714  }
715 
716  if (!noaudiocapture) {
717  snd_pcm_prepare(alsa.icard);
718  snd_pcm_start(alsa.icard);
719  }
720 
722 
723  return res;
724 }
725 
726 static char *console_sendtext(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
727 {
728  int tmparg = 3;
729  char *res = CLI_SUCCESS;
730 
731  switch (cmd) {
732  case CLI_INIT:
733  e->command = "console send text";
734  e->usage =
735  "Usage: console send text <message>\n"
736  " Sends a text message for display on the remote terminal.\n";
737  return NULL;
738  case CLI_GENERATE:
739  return NULL;
740  }
741 
742  if (a->argc < 3)
743  return CLI_SHOWUSAGE;
744 
746 
747  if (!alsa.owner) {
748  ast_cli(a->fd, "No channel active\n");
749  res = CLI_FAILURE;
750  } else {
751  struct ast_frame f = { AST_FRAME_TEXT };
752  char text2send[256] = "";
753 
754  while (tmparg < a->argc) {
755  strncat(text2send, a->argv[tmparg++], sizeof(text2send) - strlen(text2send) - 1);
756  strncat(text2send, " ", sizeof(text2send) - strlen(text2send) - 1);
757  }
758 
759  text2send[strlen(text2send) - 1] = '\n';
760  f.data.ptr = text2send;
761  f.datalen = strlen(text2send) + 1;
762  grab_owner();
763  if (alsa.owner) {
767  }
768  }
769 
771 
772  return res;
773 }
774 
775 static char *console_hangup(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
776 {
777  char *res = CLI_SUCCESS;
778 
779  switch (cmd) {
780  case CLI_INIT:
781  e->command = "console hangup";
782  e->usage =
783  "Usage: console hangup\n"
784  " Hangs up any call currently placed on the console.\n";
785  return NULL;
786  case CLI_GENERATE:
787  return NULL;
788  }
789 
790 
791  if (a->argc != 2)
792  return CLI_SHOWUSAGE;
793 
795 
796  if (!alsa.owner && !hookstate) {
797  ast_cli(a->fd, "No call to hangup\n");
798  res = CLI_FAILURE;
799  } else {
800  hookstate = 0;
801  grab_owner();
802  if (alsa.owner) {
805  }
806  }
807 
809 
810  return res;
811 }
812 
813 static char *console_dial(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
814 {
815  char tmp[256], *tmp2;
816  char *mye, *myc;
817  const char *d;
818  char *res = CLI_SUCCESS;
819 
820  switch (cmd) {
821  case CLI_INIT:
822  e->command = "console dial";
823  e->usage =
824  "Usage: console dial [extension[@context]]\n"
825  " Dials a given extension (and context if specified)\n";
826  return NULL;
827  case CLI_GENERATE:
828  return NULL;
829  }
830 
831  if ((a->argc != 2) && (a->argc != 3))
832  return CLI_SHOWUSAGE;
833 
835 
836  if (alsa.owner) {
837  if (a->argc == 3) {
838  if (alsa.owner) {
839  for (d = a->argv[2]; *d; d++) {
840  struct ast_frame f = { .frametype = AST_FRAME_DTMF, .subclass.integer = *d };
841 
843  }
844  }
845  } else {
846  ast_cli(a->fd, "You're already in a call. You can use this only to dial digits until you hangup\n");
847  res = CLI_FAILURE;
848  }
849  } else {
850  mye = exten;
851  myc = context;
852  if (a->argc == 3) {
853  char *stringp = NULL;
854 
855  ast_copy_string(tmp, a->argv[2], sizeof(tmp));
856  stringp = tmp;
857  strsep(&stringp, "@");
858  tmp2 = strsep(&stringp, "@");
859  if (!ast_strlen_zero(tmp))
860  mye = tmp;
861  if (!ast_strlen_zero(tmp2))
862  myc = tmp2;
863  }
864  if (ast_exists_extension(NULL, myc, mye, 1, NULL)) {
865  ast_copy_string(alsa.exten, mye, sizeof(alsa.exten));
866  ast_copy_string(alsa.context, myc, sizeof(alsa.context));
867  hookstate = 1;
869  } else
870  ast_cli(a->fd, "No such extension '%s' in context '%s'\n", mye, myc);
871  }
872 
874 
875  return res;
876 }
877 
878 static char *console_mute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
879 {
880  int toggle = 0;
881  char *res = CLI_SUCCESS;
882 
883  switch (cmd) {
884  case CLI_INIT:
885  e->command = "console {mute|unmute} [toggle]";
886  e->usage =
887  "Usage: console {mute|unmute} [toggle]\n"
888  " Mute/unmute the microphone.\n";
889  return NULL;
890  case CLI_GENERATE:
891  return NULL;
892  }
893 
894 
895  if (a->argc > 3) {
896  return CLI_SHOWUSAGE;
897  }
898 
899  if (a->argc == 3) {
900  if (strcasecmp(a->argv[2], "toggle"))
901  return CLI_SHOWUSAGE;
902  toggle = 1;
903  }
904 
905  if (a->argc < 2) {
906  return CLI_SHOWUSAGE;
907  }
908 
909  if (!strcasecmp(a->argv[1], "mute")) {
910  mute = toggle ? !mute : 1;
911  } else if (!strcasecmp(a->argv[1], "unmute")) {
912  mute = toggle ? !mute : 0;
913  } else {
914  return CLI_SHOWUSAGE;
915  }
916 
917  ast_cli(a->fd, "Console mic is %s\n", mute ? "off" : "on");
918 
919  return res;
920 }
921 
922 static struct ast_cli_entry cli_alsa[] = {
923  AST_CLI_DEFINE(console_answer, "Answer an incoming console call"),
924  AST_CLI_DEFINE(console_hangup, "Hangup a call on the console"),
925  AST_CLI_DEFINE(console_dial, "Dial an extension on the console"),
926  AST_CLI_DEFINE(console_sendtext, "Send text to the remote device"),
927  AST_CLI_DEFINE(console_autoanswer, "Sets/displays autoanswer"),
928  AST_CLI_DEFINE(console_mute, "Disable/Enable mic input"),
929 };
930 
931 static int unload_module(void)
932 {
933  ast_channel_unregister(&alsa_tech);
934  ast_cli_unregister_multiple(cli_alsa, ARRAY_LEN(cli_alsa));
935 
936  if (alsa.icard)
937  snd_pcm_close(alsa.icard);
938  if (alsa.ocard)
939  snd_pcm_close(alsa.ocard);
940  if (alsa.owner)
942  if (alsa.owner)
943  return -1;
944 
945  ao2_cleanup(alsa_tech.capabilities);
946  alsa_tech.capabilities = NULL;
947 
948  return 0;
949 }
950 
951 /*!
952  * \brief Load the module
953  *
954  * Module loading including tests for configuration or dependencies.
955  * This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
956  * or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
957  * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
958  * configuration file or other non-critical problem return
959  * AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
960  */
961 static int load_module(void)
962 {
963  struct ast_config *cfg;
964  struct ast_variable *v;
965  struct ast_flags config_flags = { 0 };
966 
969  }
971 
972  /* Copy the default jb config over global_jbconf */
973  memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
974 
975  strcpy(mohinterpret, "default");
976 
977  if (!(cfg = ast_config_load(config, config_flags))) {
978  ast_log(LOG_ERROR, "Unable to read ALSA configuration file %s. Aborting.\n", config);
980  } else if (cfg == CONFIG_STATUS_FILEINVALID) {
981  ast_log(LOG_ERROR, "%s is in an invalid format. Aborting.\n", config);
983  }
984 
985  v = ast_variable_browse(cfg, "general");
986  for (; v; v = v->next) {
987  /* handle jb conf */
988  if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) {
989  continue;
990  }
991 
992  if (!strcasecmp(v->name, "autoanswer")) {
993  autoanswer = ast_true(v->value);
994  } else if (!strcasecmp(v->name, "mute")) {
995  mute = ast_true(v->value);
996  } else if (!strcasecmp(v->name, "noaudiocapture")) {
998  } else if (!strcasecmp(v->name, "silencesuppression")) {
1000  } else if (!strcasecmp(v->name, "silencethreshold")) {
1001  silencethreshold = atoi(v->value);
1002  } else if (!strcasecmp(v->name, "context")) {
1003  ast_copy_string(context, v->value, sizeof(context));
1004  } else if (!strcasecmp(v->name, "language")) {
1005  ast_copy_string(language, v->value, sizeof(language));
1006  } else if (!strcasecmp(v->name, "extension")) {
1007  ast_copy_string(exten, v->value, sizeof(exten));
1008  } else if (!strcasecmp(v->name, "input_device")) {
1009  ast_copy_string(indevname, v->value, sizeof(indevname));
1010  } else if (!strcasecmp(v->name, "output_device")) {
1012  } else if (!strcasecmp(v->name, "mohinterpret")) {
1014  }
1015  }
1016  ast_config_destroy(cfg);
1017 
1018  if (soundcard_init() < 0) {
1019  ast_verb(2, "No sound card detected -- console channel will be unavailable\n");
1020  ast_verb(2, "Turn off ALSA support by adding 'noload=chan_alsa.so' in /etc/asterisk/modules.conf\n");
1021  unload_module();
1022 
1023  return AST_MODULE_LOAD_DECLINE;
1024  }
1025 
1026  if (ast_channel_register(&alsa_tech)) {
1027  ast_log(LOG_ERROR, "Unable to register channel class 'Console'\n");
1028  unload_module();
1029 
1030  return AST_MODULE_LOAD_DECLINE;
1031  }
1032 
1033  ast_cli_register_multiple(cli_alsa, ARRAY_LEN(cli_alsa));
1034 
1035  return AST_MODULE_LOAD_SUCCESS;
1036 }
1037 
1038 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "ALSA Console Channel Driver",
1039  .support_level = AST_MODULE_SUPPORT_EXTENDED,
1040  .load = load_module,
1041  .unload = unload_module,
1042  .load_pri = AST_MODPRI_CHANNEL_DRIVER,
1043 );
struct ast_variable * next
static char * console_dial(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_alsa.c:813
static const char type[]
Definition: chan_ooh323.c:109
struct ast_channel * owner
Definition: chan_alsa.c:126
enum sip_cc_notify_state state
Definition: chan_sip.c:959
char digit
static char mohinterpret[MAX_MUSICCLASS]
Definition: chan_alsa.c:119
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
#define FRAME_SIZE
Definition: chan_alsa.c:88
Main Channel structure associated with a channel.
Music on hold handling.
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
const char *const type
Definition: channel.h:630
Asterisk main include file. File version handling, generic pbx functions.
#define ALSA_OUTDEV
Definition: chan_alsa.c:84
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static const char tdesc[]
Definition: chan_alsa.c:113
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition: channel.c:1231
static struct ast_channel_tech alsa_tech
Definition: chan_alsa.c:158
snd_pcm_t * icard
Definition: chan_alsa.c:129
snd_pcm_t * ocard
Definition: chan_alsa.c:129
void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format)
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
void * ast_channel_tech_pvt(const struct ast_channel *chan)
static int silencethreshold
Definition: chan_alsa.c:109
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1216
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4322
#define MAX_MUSICCLASS
Definition: channel.h:174
static struct chan_alsa_pvt alsa
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
Definition: channel.c:570
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static int alsa_write(struct ast_channel *chan, struct ast_frame *f)
Definition: chan_alsa.c:391
#define DEADLOCK_AVOIDANCE(lock)
Definition: lock.h:374
descriptor for a cli entry.
Definition: cli.h:171
const int argc
Definition: cli.h:160
#define LOG_WARNING
Definition: logger.h:274
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:4712
#define DESIRED_RATE
Definition: chan_alsa.c:85
#define AST_FORMAT_CAP_NAMES_LEN
Definition: format_cap.h:326
static struct test_val d
int ast_jb_read_conf(struct ast_jb_conf *conf, const char *varname, const char *value)
Sets jitterbuffer configuration property.
Definition: abstract_jb.c:545
#define CONFIG_STATUS_FILEINVALID
static struct ast_jb_conf global_jbconf
Definition: chan_alsa.c:79
static int timeout
Definition: cdr_mysql.c:86
static int tmp()
Definition: bt_open.c:389
Structure for variables, used for configurations and for channel variables.
static int noaudiocapture
Definition: chan_alsa.c:145
static int alsa_text(struct ast_channel *c, const char *text)
Definition: chan_alsa.c:309
static int alsa_call(struct ast_channel *c, const char *dest, int timeout)
Definition: chan_alsa.c:325
static int autoanswer
Definition: chan_alsa.c:143
static int alsa_digit(struct ast_channel *c, char digit, unsigned int duration)
Definition: chan_alsa.c:299
Definition: cli.h:152
Structure to pass both assignedid values to channel drivers.
Definition: channel.h:605
ast_channel_state
ast_channel states
Definition: channelstate.h:35
static struct ast_channel * alsa_new(struct chan_alsa_pvt *p, int state, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
Definition: chan_alsa.c:580
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static char * console_sendtext(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_alsa.c:726
#define ast_mutex_lock(a)
Definition: lock.h:187
static struct test_val c
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:539
char * text
Definition: app_queue.c:1508
#define ast_str_alloca(init_len)
Definition: strings.h:800
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2207
static char * console_autoanswer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_alsa.c:644
#define NULL
Definition: resample.c:96
const char * data
static int alsa_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
Definition: chan_alsa.c:531
Common implementation-independent jitterbuffer stuff.
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define AST_FRAME_DTMF
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:7876
#define ast_verb(level,...)
Definition: logger.h:463
static int writedev
Definition: chan_alsa.c:141
struct ast_frame_subclass subclass
static int alsa_indicate(struct ast_channel *chan, int cond, const void *data, size_t datalen)
Definition: chan_alsa.c:542
#define MAX_LANGUAGE
Definition: channel.h:173
static int mute
Definition: chan_alsa.c:144
Utility functions.
int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
Queue a hangup frame with hangupcause set.
Definition: channel.c:1166
#define ast_module_unref(mod)
Release a reference to the module.
Definition: module.h:469
#define ast_strlen_zero(foo)
Definition: strings.h:52
enum ast_format_cmp_res ast_format_cap_iscompatible_format(const struct ast_format_cap *cap, const struct ast_format *format)
Find if ast_format is within the capabilities of the ast_format_cap object.
Definition: format_cap.c:583
void ast_channel_tech_set(struct ast_channel *chan, const struct ast_channel_tech *value)
Configuration File Parser.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define ast_config_load(filename, flags)
Load a config file.
struct ast_module * self
Definition: module.h:342
General Asterisk PBX channel definitions.
#define AST_FRIENDLY_OFFSET
Offset into a frame&#39;s data buffer.
const char * src
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)
Definition: chan_alsa.c:620
const int fd
Definition: cli.h:159
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
Asterisk architecture endianess compatibility definitions.
ast_cond_t cond
Definition: app_meetme.c:1090
#define AST_MAX_EXTENSION
Definition: channel.h:135
#define AST_CAUSE_NORMAL_CLEARING
Definition: causes.h:105
static int load_module(void)
Load the module.
Definition: chan_alsa.c:961
Asterisk internal frame definitions.
void ast_channel_set_readformat(struct ast_channel *chan, struct ast_format *format)
int ast_softhangup(struct ast_channel *chan, int reason)
Softly hangup up a channel.
Definition: channel.c:2476
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
static int soundcard_init(void)
Definition: chan_alsa.c:279
#define ast_format_cap_append(cap, format, framing)
Definition: format_cap.h:103
static char language[MAX_LANGUAGE]
Definition: chan_alsa.c:117
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:4179
#define ast_format_cap_alloc(flags)
Definition: format_cap.h:52
Structure to describe a channel "technology", ie a channel driver See for examples: ...
Definition: channel.h:629
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:1139
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
const char *const * argv
Definition: cli.h:161
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
#define LOG_ERROR
Definition: logger.h:285
static char outdevname[50]
Definition: chan_alsa.c:106
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".
Definition: main/utils.c:1951
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
#define CLI_SHOWUSAGE
Definition: cli.h:45
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static ast_mutex_t alsalock
Definition: chan_alsa.c:111
char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:128
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:7866
char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:127
#define LOG_NOTICE
Definition: logger.h:263
const char * ast_format_cap_get_names(const struct ast_format_cap *cap, struct ast_str **buf)
Get the names of codecs of a set of formats.
Definition: format_cap.c:736
struct ast_format_cap * capabilities
Definition: channel.h:633
static char indevname[50]
Definition: chan_alsa.c:105
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define CLI_FAILURE
Definition: cli.h:46
static struct ast_cli_entry cli_alsa[]
Definition: chan_alsa.c:922
#define AST_MAX_CONTEXT
Definition: channel.h:136
char * command
Definition: cli.h:186
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2548
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
#define PERIOD_FRAMES
Definition: chan_alsa.c:89
unsigned int flags
Combination of the AST_JB_ENABLED, AST_JB_FORCED and AST_JB_LOG flags.
Definition: abstract_jb.h:72
static char * console_hangup(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_alsa.c:775
Structure used to handle boolean flags.
Definition: utils.h:199
static struct ast_frame * alsa_read(struct ast_channel *chan)
Definition: chan_alsa.c:443
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
Definition: channel.c:2431
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
struct timeval delivery
void ast_jb_configure(struct ast_channel *chan, const struct ast_jb_conf *conf)
Configures a jitterbuffer on a channel.
Definition: abstract_jb.c:593
const char * usage
Definition: cli.h:177
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
#define CLI_SUCCESS
Definition: cli.h:44
static char * console_mute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_alsa.c:878
static void grab_owner(void)
Definition: chan_alsa.c:318
char * strsep(char **str, const char *delims)
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
Standard Command Line Interface.
void ast_channel_context_set(struct ast_channel *chan, const char *value)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
const char * ast_channel_name(const struct ast_channel *chan)
static snd_pcm_t * alsa_card_init(char *dev, snd_pcm_stream_t stream)
Definition: chan_alsa.c:173
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7486
static int hookstate
Definition: chan_alsa.c:121
#define AST_CAUSE_BUSY
Definition: causes.h:148
Data structure associated with a single frame of data.
#define ESTRPIPE
Definition: chan_alsa.c:44
Internal Asterisk hangup causes.
static const char config[]
Definition: chan_alsa.c:114
union ast_frame::@263 data
enum ast_frame_type frametype
#define ast_channel_trylock(chan)
Definition: channel.h:2947
static char * console_answer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_alsa.c:680
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
struct ast_format * format
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
direction
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition: channel.h:1259
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
Asterisk module definitions.
static int alsa_answer(struct ast_channel *c)
Definition: chan_alsa.c:361
static snd_pcm_format_t format
Definition: chan_alsa.c:102
void ast_channel_tech_pvt_set(struct ast_channel *chan, void *value)
static int readdev
Definition: chan_alsa.c:140
General jitterbuffer configuration.
Definition: abstract_jb.h:69
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:518
static struct ast_jb_conf default_jbconf
Definition: chan_alsa.c:72
static int silencesuppression
Definition: chan_alsa.c:108
static int unload_module(void)
Definition: chan_alsa.c:931
Media Format Cache API.
#define ast_mutex_unlock(a)
Definition: lock.h:188
static struct test_val a
static int alsa_hangup(struct ast_channel *c)
Definition: chan_alsa.c:375
#define ast_module_ref(mod)
Hold a reference to the module.
Definition: module.h:443
#define ALSA_INDEV
Definition: chan_alsa.c:83