2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2005, Digium, Inc.
6 * By Matthew Fredrickson <creslin@digium.com>
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.
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.
20 * \brief ALSA sound card channel driver
22 * \author Matthew Fredrickson <creslin@digium.com>
27 * \ingroup channel_drivers
31 <depend>asound</depend>
36 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
41 #include <sys/ioctl.h>
47 #define ALSA_PCM_NEW_HW_PARAMS_API
48 #define ALSA_PCM_NEW_SW_PARAMS_API
49 #include <alsa/asoundlib.h>
51 #include "asterisk/frame.h"
52 #include "asterisk/logger.h"
53 #include "asterisk/channel.h"
54 #include "asterisk/module.h"
55 #include "asterisk/options.h"
56 #include "asterisk/pbx.h"
57 #include "asterisk/config.h"
58 #include "asterisk/cli.h"
59 #include "asterisk/utils.h"
60 #include "asterisk/causes.h"
61 #include "asterisk/endian.h"
62 #include "asterisk/stringfields.h"
63 #include "asterisk/abstract_jb.h"
64 #include "asterisk/musiconhold.h"
72 #include "alsa-monitor.h"
75 /*! Global jitterbuffer configuration - by default, jb is disabled */
76 static struct ast_jb_conf default_jbconf
= {
79 .resync_threshold
= -1,
82 static struct ast_jb_conf global_jbconf
;
85 /* Which device to use */
86 #define ALSA_INDEV "default"
87 #define ALSA_OUTDEV "default"
88 #define DESIRED_RATE 8000
90 /* Lets use 160 sample frames, just like GSM. */
91 #define FRAME_SIZE 160
92 #define PERIOD_FRAMES 80 /* 80 Frames, at 2 bytes each */
94 /* When you set the frame size, you have to come up with
95 the right buffer format as well. */
96 /* 5 64-byte frames = one frame */
97 #define BUFFER_FMT ((buffersize * 10) << 16) | (0x0006);
99 /* Don't switch between read/write modes faster than every 300 ms */
100 #define MIN_SWITCH_TIME 600
102 #if __BYTE_ORDER == __LITTLE_ENDIAN
103 static snd_pcm_format_t format
= SND_PCM_FORMAT_S16_LE
;
105 static snd_pcm_format_t format
= SND_PCM_FORMAT_S16_BE
;
108 /* static int block = O_NONBLOCK; */
109 static char indevname
[50] = ALSA_INDEV
;
110 static char outdevname
[50] = ALSA_OUTDEV
;
113 static struct timeval lasttime
;
116 static int silencesuppression
= 0;
117 static int silencethreshold
= 1000;
119 AST_MUTEX_DEFINE_STATIC(alsalock
);
121 static const char tdesc
[] = "ALSA Console Channel Driver";
122 static const char config
[] = "alsa.conf";
124 static char context
[AST_MAX_CONTEXT
] = "default";
125 static char language
[MAX_LANGUAGE
] = "";
126 static char exten
[AST_MAX_EXTENSION
] = "s";
127 static char mohinterpret
[MAX_MUSICCLASS
];
129 static int hookstate
= 0;
131 static short silence
[FRAME_SIZE
] = { 0, };
142 static struct sound sounds
[] = {
143 {AST_CONTROL_RINGING
, ringtone
, sizeof(ringtone
) / 2, 16000, 32000, 1},
144 {AST_CONTROL_BUSY
, busy
, sizeof(busy
) / 2, 4000, 4000, 1},
145 {AST_CONTROL_CONGESTION
, busy
, sizeof(busy
) / 2, 2000, 2000, 1},
146 {AST_CONTROL_RING
, ring10
, sizeof(ring10
) / 2, 16000, 32000, 1},
147 {AST_CONTROL_ANSWER
, answer
, sizeof(answer
) / 2, 2200, 0, 0},
150 /* Sound command pipe */
151 static int sndcmd
[2];
153 static struct chan_alsa_pvt
{
154 /* We only have one ALSA structure -- near sighted perhaps, but it
155 keeps this driver as simple as possible -- as it should be. */
156 struct ast_channel
*owner
;
157 char exten
[AST_MAX_EXTENSION
];
158 char context
[AST_MAX_CONTEXT
];
162 snd_pcm_t
*icard
, *ocard
;
166 /* Number of buffers... Each is FRAMESIZE/8 ms long. For example
167 with 160 sample frames, and a buffer size of 3, we have a 60ms buffer,
172 #define MAX_BUFFER_SIZE 100
174 /* File descriptors for sound device */
175 static int readdev
= -1;
176 static int writedev
= -1;
178 static int autoanswer
= 1;
180 static int cursound
= -1;
181 static int sampsent
= 0;
182 static int silencelen
= 0;
183 static int offset
= 0;
184 static int nosound
= 0;
187 static struct ast_channel
*alsa_request(const char *type
, int format
, void *data
, int *cause
);
188 static int alsa_digit(struct ast_channel
*c
, char digit
, unsigned int duration
);
189 static int alsa_text(struct ast_channel
*c
, const char *text
);
190 static int alsa_hangup(struct ast_channel
*c
);
191 static int alsa_answer(struct ast_channel
*c
);
192 static struct ast_frame
*alsa_read(struct ast_channel
*chan
);
193 static int alsa_call(struct ast_channel
*c
, char *dest
, int timeout
);
194 static int alsa_write(struct ast_channel
*chan
, struct ast_frame
*f
);
195 static int alsa_indicate(struct ast_channel
*chan
, int cond
, const void *data
, size_t datalen
);
196 static int alsa_fixup(struct ast_channel
*oldchan
, struct ast_channel
*newchan
);
198 static const struct ast_channel_tech alsa_tech
= {
200 .description
= tdesc
,
201 .capabilities
= AST_FORMAT_SLINEAR
,
202 .requester
= alsa_request
,
203 .send_digit_end
= alsa_digit
,
204 .send_text
= alsa_text
,
205 .hangup
= alsa_hangup
,
206 .answer
= alsa_answer
,
210 .indicate
= alsa_indicate
,
214 static int send_sound(void)
216 short myframe
[FRAME_SIZE
];
217 int total
= FRAME_SIZE
;
219 int amt
= 0, res
, myoff
;
220 snd_pcm_state_t state
;
226 if (sampsent
< sounds
[cursound
].samplen
) {
230 if (amt
> (sounds
[cursound
].datalen
- offset
))
231 amt
= sounds
[cursound
].datalen
- offset
;
232 memcpy(myframe
+ myoff
, sounds
[cursound
].data
+ offset
, amt
* 2);
237 if (offset
>= sounds
[cursound
].datalen
)
240 /* Set it up for silence */
241 if (sampsent
>= sounds
[cursound
].samplen
)
242 silencelen
= sounds
[cursound
].silencelen
;
245 if (silencelen
> 0) {
249 if (sounds
[cursound
].repeat
) {
261 if (res
== 0 || !frame
)
265 alsa_monitor_write((char *) frame
, res
* 2);
267 state
= snd_pcm_state(alsa
.ocard
);
268 if (state
== SND_PCM_STATE_XRUN
)
269 snd_pcm_prepare(alsa
.ocard
);
270 res
= snd_pcm_writei(alsa
.ocard
, frame
, res
);
276 static void *sound_thread(void *unused
)
286 FD_SET(sndcmd
[0], &rfds
);
288 FD_SET(writedev
, &wfds
);
294 FD_SET(readdev
, &rfds
);
299 res
= ast_select(max
+ 1, &rfds
, &wfds
, NULL
, NULL
);
301 ast_log(LOG_WARNING
, "select failed: %s\n", strerror(errno
));
305 if (FD_ISSET(readdev
, &rfds
)) {
306 /* Keep the pipe going with read audio */
307 snd_pcm_state_t state
;
308 short buf
[FRAME_SIZE
];
311 state
= snd_pcm_state(alsa
.ocard
);
312 if (state
== SND_PCM_STATE_XRUN
) {
313 snd_pcm_prepare(alsa
.ocard
);
315 r
= snd_pcm_readi(alsa
.icard
, buf
, FRAME_SIZE
);
318 ast_log(LOG_ERROR
, "XRUN read\n");
320 snd_pcm_prepare(alsa
.icard
);
321 } else if (r
== -ESTRPIPE
) {
322 ast_log(LOG_ERROR
, "-ESTRPIPE\n");
323 snd_pcm_prepare(alsa
.icard
);
325 ast_log(LOG_ERROR
, "Read error: %s\n", snd_strerror(r
));
327 alsa_monitor_read((char *) buf
, r
* 2);
330 if (FD_ISSET(sndcmd
[0], &rfds
)) {
331 read(sndcmd
[0], &cursound
, sizeof(cursound
));
336 if (FD_ISSET(writedev
, &wfds
))
338 ast_log(LOG_WARNING
, "Failed to write sound\n");
344 static snd_pcm_t
*alsa_card_init(char *dev
, snd_pcm_stream_t stream
)
348 snd_pcm_t
*handle
= NULL
;
349 snd_pcm_hw_params_t
*hwparams
= NULL
;
350 snd_pcm_sw_params_t
*swparams
= NULL
;
352 snd_pcm_uframes_t period_size
= PERIOD_FRAMES
* 4;
353 /* int period_bytes = 0; */
354 snd_pcm_uframes_t buffer_size
= 0;
356 unsigned int rate
= DESIRED_RATE
;
358 unsigned int per_min
= 1;
360 /* unsigned int per_max = 8; */
361 snd_pcm_uframes_t start_threshold
, stop_threshold
;
363 err
= snd_pcm_open(&handle
, dev
, stream
, O_NONBLOCK
);
365 ast_log(LOG_ERROR
, "snd_pcm_open failed: %s\n", snd_strerror(err
));
368 ast_log(LOG_DEBUG
, "Opening device %s in %s mode\n", dev
, (stream
== SND_PCM_STREAM_CAPTURE
) ? "read" : "write");
370 snd_pcm_hw_params_alloca(&hwparams
);
371 snd_pcm_hw_params_any(handle
, hwparams
);
373 err
= snd_pcm_hw_params_set_access(handle
, hwparams
, SND_PCM_ACCESS_RW_INTERLEAVED
);
375 ast_log(LOG_ERROR
, "set_access failed: %s\n", snd_strerror(err
));
377 err
= snd_pcm_hw_params_set_format(handle
, hwparams
, format
);
379 ast_log(LOG_ERROR
, "set_format failed: %s\n", snd_strerror(err
));
381 err
= snd_pcm_hw_params_set_channels(handle
, hwparams
, 1);
383 ast_log(LOG_ERROR
, "set_channels failed: %s\n", snd_strerror(err
));
386 err
= snd_pcm_hw_params_set_rate_near(handle
, hwparams
, &rate
, &direction
);
387 if (rate
!= DESIRED_RATE
)
388 ast_log(LOG_WARNING
, "Rate not correct, requested %d, got %d\n", DESIRED_RATE
, rate
);
391 err
= snd_pcm_hw_params_set_period_size_near(handle
, hwparams
, &period_size
, &direction
);
393 ast_log(LOG_ERROR
, "period_size(%ld frames) is bad: %s\n", period_size
, snd_strerror(err
));
395 ast_log(LOG_DEBUG
, "Period size is %d\n", err
);
397 buffer_size
= 4096 * 2; /* period_size * 16; */
398 err
= snd_pcm_hw_params_set_buffer_size_near(handle
, hwparams
, &buffer_size
);
400 ast_log(LOG_WARNING
, "Problem setting buffer size of %ld: %s\n", buffer_size
, snd_strerror(err
));
402 ast_log(LOG_DEBUG
, "Buffer size is set to %d frames\n", err
);
406 err
= snd_pcm_hw_params_set_periods_min(handle
, hwparams
, &per_min
, &direction
);
408 ast_log(LOG_ERROR
, "periods_min: %s\n", snd_strerror(err
));
410 err
= snd_pcm_hw_params_set_periods_max(handle
, hwparams
, &per_max
, 0);
412 ast_log(LOG_ERROR
, "periods_max: %s\n", snd_strerror(err
));
415 err
= snd_pcm_hw_params(handle
, hwparams
);
417 ast_log(LOG_ERROR
, "Couldn't set the new hw params: %s\n", snd_strerror(err
));
419 snd_pcm_sw_params_alloca(&swparams
);
420 snd_pcm_sw_params_current(handle
, swparams
);
423 if (stream
== SND_PCM_STREAM_PLAYBACK
)
424 start_threshold
= period_size
;
428 err
= snd_pcm_sw_params_set_start_threshold(handle
, swparams
, start_threshold
);
430 ast_log(LOG_ERROR
, "start threshold: %s\n", snd_strerror(err
));
434 if (stream
== SND_PCM_STREAM_PLAYBACK
)
435 stop_threshold
= buffer_size
;
437 stop_threshold
= buffer_size
;
439 err
= snd_pcm_sw_params_set_stop_threshold(handle
, swparams
, stop_threshold
);
441 ast_log(LOG_ERROR
, "stop threshold: %s\n", snd_strerror(err
));
444 err
= snd_pcm_sw_params_set_xfer_align(handle
, swparams
, PERIOD_FRAMES
);
446 ast_log(LOG_ERROR
, "Unable to set xfer alignment: %s\n", snd_strerror(err
));
450 err
= snd_pcm_sw_params_set_silence_threshold(handle
, swparams
, silencethreshold
);
452 ast_log(LOG_ERROR
, "Unable to set silence threshold: %s\n", snd_strerror(err
));
454 err
= snd_pcm_sw_params(handle
, swparams
);
456 ast_log(LOG_ERROR
, "sw_params: %s\n", snd_strerror(err
));
458 err
= snd_pcm_poll_descriptors_count(handle
);
460 ast_log(LOG_ERROR
, "Unable to get a poll descriptors count, error is %s\n", snd_strerror(err
));
462 ast_log(LOG_DEBUG
, "Can't handle more than one device\n");
464 snd_pcm_poll_descriptors(handle
, &pfd
, err
);
465 ast_log(LOG_DEBUG
, "Acquired fd %d from the poll descriptor\n", pfd
.fd
);
467 if (stream
== SND_PCM_STREAM_CAPTURE
)
475 static int soundcard_init(void)
477 alsa
.icard
= alsa_card_init(indevname
, SND_PCM_STREAM_CAPTURE
);
478 alsa
.ocard
= alsa_card_init(outdevname
, SND_PCM_STREAM_PLAYBACK
);
480 if (!alsa
.icard
|| !alsa
.ocard
) {
481 ast_log(LOG_ERROR
, "Problem opening alsa I/O devices\n");
488 static int alsa_digit(struct ast_channel
*c
, char digit
, unsigned int duration
)
490 ast_mutex_lock(&alsalock
);
491 ast_verbose(" << Console Received digit %c of duration %u ms >> \n",
493 ast_mutex_unlock(&alsalock
);
497 static int alsa_text(struct ast_channel
*c
, const char *text
)
499 ast_mutex_lock(&alsalock
);
500 ast_verbose(" << Console Received text %s >> \n", text
);
501 ast_mutex_unlock(&alsalock
);
505 static void grab_owner(void)
507 while (alsa
.owner
&& ast_mutex_trylock(&alsa
.owner
->lock
)) {
508 ast_mutex_unlock(&alsalock
);
510 ast_mutex_lock(&alsalock
);
514 static int alsa_call(struct ast_channel
*c
, char *dest
, int timeout
)
517 struct ast_frame f
= { AST_FRAME_CONTROL
};
518 ast_mutex_lock(&alsalock
);
519 ast_verbose(" << Call placed to '%s' on console >> \n", dest
);
521 ast_verbose(" << Auto-answered >> \n");
524 f
.subclass
= AST_CONTROL_ANSWER
;
525 ast_queue_frame(alsa
.owner
, &f
);
526 ast_mutex_unlock(&alsa
.owner
->lock
);
529 ast_verbose(" << Type 'answer' to answer, or use 'autoanswer' for future calls >> \n");
532 f
.subclass
= AST_CONTROL_RINGING
;
533 ast_queue_frame(alsa
.owner
, &f
);
534 ast_mutex_unlock(&alsa
.owner
->lock
);
536 write(sndcmd
[1], &res
, sizeof(res
));
538 snd_pcm_prepare(alsa
.icard
);
539 snd_pcm_start(alsa
.icard
);
540 ast_mutex_unlock(&alsalock
);
544 static void answer_sound(void)
549 write(sndcmd
[1], &res
, sizeof(res
));
553 static int alsa_answer(struct ast_channel
*c
)
555 ast_mutex_lock(&alsalock
);
556 ast_verbose(" << Console call has been answered >> \n");
558 ast_setstate(c
, AST_STATE_UP
);
560 snd_pcm_prepare(alsa
.icard
);
561 snd_pcm_start(alsa
.icard
);
562 ast_mutex_unlock(&alsalock
);
566 static int alsa_hangup(struct ast_channel
*c
)
569 ast_mutex_lock(&alsalock
);
573 ast_verbose(" << Hangup on console >> \n");
574 ast_module_unref(ast_module_info
->self
);
578 /* Congestion noise */
580 write(sndcmd
[1], &res
, sizeof(res
));
583 snd_pcm_drop(alsa
.icard
);
584 ast_mutex_unlock(&alsalock
);
588 static int alsa_write(struct ast_channel
*chan
, struct ast_frame
*f
)
590 static char sizbuf
[8000];
591 static int sizpos
= 0;
595 /* size_t frames = 0; */
596 snd_pcm_state_t state
;
598 /* Immediately return if no sound is enabled */
602 ast_mutex_lock(&alsalock
);
603 /* Stop any currently playing sound */
604 if (cursound
!= -1) {
605 snd_pcm_drop(alsa
.ocard
);
606 snd_pcm_prepare(alsa
.ocard
);
611 /* We have to digest the frame in 160-byte portions */
612 if (f
->datalen
> sizeof(sizbuf
) - sizpos
) {
613 ast_log(LOG_WARNING
, "Frame too large\n");
616 memcpy(sizbuf
+ sizpos
, f
->data
, f
->datalen
);
620 alsa_monitor_write(sizbuf
, len
);
622 state
= snd_pcm_state(alsa
.ocard
);
623 if (state
== SND_PCM_STATE_XRUN
)
624 snd_pcm_prepare(alsa
.ocard
);
625 res
= snd_pcm_writei(alsa
.ocard
, sizbuf
, len
/ 2);
628 ast_log(LOG_DEBUG
, "XRUN write\n");
630 snd_pcm_prepare(alsa
.ocard
);
631 res
= snd_pcm_writei(alsa
.ocard
, sizbuf
, len
/ 2);
632 if (res
!= len
/ 2) {
633 ast_log(LOG_ERROR
, "Write error: %s\n", snd_strerror(res
));
635 } else if (res
< 0) {
636 ast_log(LOG_ERROR
, "Write error %s\n", snd_strerror(res
));
640 if (res
== -ESTRPIPE
)
641 ast_log(LOG_ERROR
, "You've got some big problems\n");
643 ast_log(LOG_NOTICE
, "Error %d on write\n", res
);
646 ast_mutex_unlock(&alsalock
);
653 static struct ast_frame
*alsa_read(struct ast_channel
*chan
)
655 static struct ast_frame f
;
656 static short __buf
[FRAME_SIZE
+ AST_FRIENDLY_OFFSET
/ 2];
658 static int readpos
= 0;
659 static int left
= FRAME_SIZE
;
660 snd_pcm_state_t state
;
664 ast_mutex_lock(&alsalock
);
665 /* Acknowledge any pending cmd */
666 f
.frametype
= AST_FRAME_NULL
;
674 f
.delivery
.tv_sec
= 0;
675 f
.delivery
.tv_usec
= 0;
677 state
= snd_pcm_state(alsa
.icard
);
678 if ((state
!= SND_PCM_STATE_PREPARED
) && (state
!= SND_PCM_STATE_RUNNING
)) {
679 snd_pcm_prepare(alsa
.icard
);
682 buf
= __buf
+ AST_FRIENDLY_OFFSET
/ 2;
684 r
= snd_pcm_readi(alsa
.icard
, buf
+ readpos
, left
);
687 ast_log(LOG_ERROR
, "XRUN read\n");
689 snd_pcm_prepare(alsa
.icard
);
690 } else if (r
== -ESTRPIPE
) {
691 ast_log(LOG_ERROR
, "-ESTRPIPE\n");
692 snd_pcm_prepare(alsa
.icard
);
694 ast_log(LOG_ERROR
, "Read error: %s\n", snd_strerror(r
));
698 /* Update positions */
702 if (readpos
>= FRAME_SIZE
) {
706 if (chan
->_state
!= AST_STATE_UP
) {
707 /* Don't transmit unless it's up */
708 ast_mutex_unlock(&alsalock
);
711 f
.frametype
= AST_FRAME_VOICE
;
712 f
.subclass
= AST_FORMAT_SLINEAR
;
713 f
.samples
= FRAME_SIZE
;
714 f
.datalen
= FRAME_SIZE
* 2;
716 f
.offset
= AST_FRIENDLY_OFFSET
;
720 alsa_monitor_read((char *) buf
, FRAME_SIZE
* 2);
724 ast_mutex_unlock(&alsalock
);
728 static int alsa_fixup(struct ast_channel
*oldchan
, struct ast_channel
*newchan
)
730 struct chan_alsa_pvt
*p
= newchan
->tech_pvt
;
731 ast_mutex_lock(&alsalock
);
733 ast_mutex_unlock(&alsalock
);
737 static int alsa_indicate(struct ast_channel
*chan
, int cond
, const void *data
, size_t datalen
)
741 ast_mutex_lock(&alsalock
);
744 case AST_CONTROL_BUSY
:
747 case AST_CONTROL_CONGESTION
:
750 case AST_CONTROL_RINGING
:
755 case AST_CONTROL_VIDUPDATE
:
758 case AST_CONTROL_HOLD
:
759 ast_verbose(" << Console Has Been Placed on Hold >> \n");
760 ast_moh_start(chan
, data
, mohinterpret
);
762 case AST_CONTROL_UNHOLD
:
763 ast_verbose(" << Console Has Been Retrieved from Hold >> \n");
767 ast_log(LOG_WARNING
, "Don't know how to display condition %d on %s\n", cond
, chan
->name
);
772 write(sndcmd
[1], &res
, sizeof(res
));
774 ast_mutex_unlock(&alsalock
);
779 static struct ast_channel
*alsa_new(struct chan_alsa_pvt
*p
, int state
)
781 struct ast_channel
*tmp
= NULL
;
783 if (!(tmp
= ast_channel_alloc(1, state
, 0, 0, "ALSA/%s", indevname
)))
786 tmp
->tech
= &alsa_tech
;
787 tmp
->fds
[0] = readdev
;
788 tmp
->nativeformats
= AST_FORMAT_SLINEAR
;
789 tmp
->readformat
= AST_FORMAT_SLINEAR
;
790 tmp
->writeformat
= AST_FORMAT_SLINEAR
;
792 if (!ast_strlen_zero(p
->context
))
793 ast_copy_string(tmp
->context
, p
->context
, sizeof(tmp
->context
));
794 if (!ast_strlen_zero(p
->exten
))
795 ast_copy_string(tmp
->exten
, p
->exten
, sizeof(tmp
->exten
));
796 if (!ast_strlen_zero(language
))
797 ast_string_field_set(tmp
, language
, language
);
799 ast_module_ref(ast_module_info
->self
);
800 ast_jb_configure(tmp
, &global_jbconf
);
801 if (state
!= AST_STATE_DOWN
) {
802 if (ast_pbx_start(tmp
)) {
803 ast_log(LOG_WARNING
, "Unable to start PBX on %s\n", tmp
->name
);
812 static struct ast_channel
*alsa_request(const char *type
, int format
, void *data
, int *cause
)
814 int oldformat
= format
;
815 struct ast_channel
*tmp
= NULL
;
817 format
&= AST_FORMAT_SLINEAR
;
819 ast_log(LOG_NOTICE
, "Asked to get a channel of format '%d'\n", oldformat
);
823 ast_mutex_lock(&alsalock
);
826 ast_log(LOG_NOTICE
, "Already have a call on the ALSA channel\n");
827 *cause
= AST_CAUSE_BUSY
;
828 } else if (!(tmp
= alsa_new(&alsa
, AST_STATE_DOWN
)))
829 ast_log(LOG_WARNING
, "Unable to create new ALSA channel\n");
831 ast_mutex_unlock(&alsalock
);
836 static int console_autoanswer_deprecated(int fd
, int argc
, char *argv
[])
838 int res
= RESULT_SUCCESS
;
840 if ((argc
!= 1) && (argc
!= 2))
841 return RESULT_SHOWUSAGE
;
843 ast_mutex_lock(&alsalock
);
846 ast_cli(fd
, "Auto answer is %s.\n", autoanswer
? "on" : "off");
848 if (!strcasecmp(argv
[1], "on"))
850 else if (!strcasecmp(argv
[1], "off"))
853 res
= RESULT_SHOWUSAGE
;
856 ast_mutex_unlock(&alsalock
);
861 static int console_autoanswer(int fd
, int argc
, char *argv
[])
863 int res
= RESULT_SUCCESS
;;
864 if ((argc
!= 2) && (argc
!= 3))
865 return RESULT_SHOWUSAGE
;
866 ast_mutex_lock(&alsalock
);
868 ast_cli(fd
, "Auto answer is %s.\n", autoanswer
? "on" : "off");
870 if (!strcasecmp(argv
[2], "on"))
872 else if (!strcasecmp(argv
[2], "off"))
875 res
= RESULT_SHOWUSAGE
;
877 ast_mutex_unlock(&alsalock
);
881 static char *autoanswer_complete(const char *line
, const char *word
, int pos
, int state
)
884 #define MIN(a,b) ((a) < (b) ? (a) : (b))
888 if (!ast_strlen_zero(word
) && !strncasecmp(word
, "on", MIN(strlen(word
), 2)))
889 return ast_strdup("on");
891 if (!ast_strlen_zero(word
) && !strncasecmp(word
, "off", MIN(strlen(word
), 3)))
892 return ast_strdup("off");
899 static const char autoanswer_usage
[] =
900 "Usage: console autoanswer [on|off]\n"
901 " Enables or disables autoanswer feature. If used without\n"
902 " argument, displays the current on/off status of autoanswer.\n"
903 " The default value of autoanswer is in 'alsa.conf'.\n";
905 static int console_answer_deprecated(int fd
, int argc
, char *argv
[])
907 int res
= RESULT_SUCCESS
;
910 return RESULT_SHOWUSAGE
;
912 ast_mutex_lock(&alsalock
);
915 ast_cli(fd
, "No one is calling us\n");
916 res
= RESULT_FAILURE
;
922 struct ast_frame f
= { AST_FRAME_CONTROL
, AST_CONTROL_ANSWER
};
923 ast_queue_frame(alsa
.owner
, &f
);
924 ast_mutex_unlock(&alsa
.owner
->lock
);
929 snd_pcm_prepare(alsa
.icard
);
930 snd_pcm_start(alsa
.icard
);
932 ast_mutex_unlock(&alsalock
);
934 return RESULT_SUCCESS
;
937 static int console_answer(int fd
, int argc
, char *argv
[])
939 int res
= RESULT_SUCCESS
;
942 return RESULT_SHOWUSAGE
;
944 ast_mutex_lock(&alsalock
);
947 ast_cli(fd
, "No one is calling us\n");
948 res
= RESULT_FAILURE
;
954 struct ast_frame f
= { AST_FRAME_CONTROL
, AST_CONTROL_ANSWER
};
955 ast_queue_frame(alsa
.owner
, &f
);
956 ast_mutex_unlock(&alsa
.owner
->lock
);
961 snd_pcm_prepare(alsa
.icard
);
962 snd_pcm_start(alsa
.icard
);
964 ast_mutex_unlock(&alsalock
);
966 return RESULT_SUCCESS
;
969 static char sendtext_usage
[] =
970 "Usage: console send text <message>\n"
971 " Sends a text message for display on the remote terminal.\n";
973 static int console_sendtext_deprecated(int fd
, int argc
, char *argv
[])
976 int res
= RESULT_SUCCESS
;
979 return RESULT_SHOWUSAGE
;
981 ast_mutex_lock(&alsalock
);
984 ast_cli(fd
, "No one is calling us\n");
985 res
= RESULT_FAILURE
;
987 struct ast_frame f
= { AST_FRAME_TEXT
, 0 };
988 char text2send
[256] = "";
990 while (tmparg
< argc
) {
991 strncat(text2send
, argv
[tmparg
++], sizeof(text2send
) - strlen(text2send
) - 1);
992 strncat(text2send
, " ", sizeof(text2send
) - strlen(text2send
) - 1);
994 text2send
[strlen(text2send
) - 1] = '\n';
996 f
.datalen
= strlen(text2send
) + 1;
999 ast_queue_frame(alsa
.owner
, &f
);
1000 f
.frametype
= AST_FRAME_CONTROL
;
1001 f
.subclass
= AST_CONTROL_ANSWER
;
1004 ast_queue_frame(alsa
.owner
, &f
);
1005 ast_mutex_unlock(&alsa
.owner
->lock
);
1009 ast_mutex_unlock(&alsalock
);
1014 static int console_sendtext(int fd
, int argc
, char *argv
[])
1017 int res
= RESULT_SUCCESS
;
1020 return RESULT_SHOWUSAGE
;
1022 ast_mutex_lock(&alsalock
);
1025 ast_cli(fd
, "No one is calling us\n");
1026 res
= RESULT_FAILURE
;
1028 struct ast_frame f
= { AST_FRAME_TEXT
, 0 };
1029 char text2send
[256] = "";
1030 text2send
[0] = '\0';
1031 while (tmparg
< argc
) {
1032 strncat(text2send
, argv
[tmparg
++], sizeof(text2send
) - strlen(text2send
) - 1);
1033 strncat(text2send
, " ", sizeof(text2send
) - strlen(text2send
) - 1);
1035 text2send
[strlen(text2send
) - 1] = '\n';
1037 f
.datalen
= strlen(text2send
) + 1;
1040 ast_queue_frame(alsa
.owner
, &f
);
1041 f
.frametype
= AST_FRAME_CONTROL
;
1042 f
.subclass
= AST_CONTROL_ANSWER
;
1045 ast_queue_frame(alsa
.owner
, &f
);
1046 ast_mutex_unlock(&alsa
.owner
->lock
);
1050 ast_mutex_unlock(&alsalock
);
1055 static char answer_usage
[] =
1056 "Usage: console answer\n"
1057 " Answers an incoming call on the console (ALSA) channel.\n";
1059 static int console_hangup_deprecated(int fd
, int argc
, char *argv
[])
1061 int res
= RESULT_SUCCESS
;
1064 return RESULT_SHOWUSAGE
;
1068 ast_mutex_lock(&alsalock
);
1070 if (!alsa
.owner
&& !hookstate
) {
1071 ast_cli(fd
, "No call to hangup up\n");
1072 res
= RESULT_FAILURE
;
1077 ast_queue_hangup(alsa
.owner
);
1078 ast_mutex_unlock(&alsa
.owner
->lock
);
1082 ast_mutex_unlock(&alsalock
);
1087 static int console_hangup(int fd
, int argc
, char *argv
[])
1089 int res
= RESULT_SUCCESS
;
1092 return RESULT_SHOWUSAGE
;
1096 ast_mutex_lock(&alsalock
);
1098 if (!alsa
.owner
&& !hookstate
) {
1099 ast_cli(fd
, "No call to hangup up\n");
1100 res
= RESULT_FAILURE
;
1105 ast_queue_hangup(alsa
.owner
);
1106 ast_mutex_unlock(&alsa
.owner
->lock
);
1110 ast_mutex_unlock(&alsalock
);
1115 static char hangup_usage
[] =
1116 "Usage: console hangup\n"
1117 " Hangs up any call currently placed on the console.\n";
1119 static int console_dial_deprecated(int fd
, int argc
, char *argv
[])
1121 char tmp
[256], *tmp2
;
1124 int res
= RESULT_SUCCESS
;
1126 if ((argc
!= 1) && (argc
!= 2))
1127 return RESULT_SHOWUSAGE
;
1129 ast_mutex_lock(&alsalock
);
1136 struct ast_frame f
= { AST_FRAME_DTMF
};
1139 ast_queue_frame(alsa
.owner
, &f
);
1142 ast_mutex_unlock(&alsa
.owner
->lock
);
1145 ast_cli(fd
, "You're already in a call. You can use this only to dial digits until you hangup\n");
1146 res
= RESULT_FAILURE
;
1152 char *stringp
= NULL
;
1153 ast_copy_string(tmp
, argv
[1], sizeof(tmp
));
1155 strsep(&stringp
, "@");
1156 tmp2
= strsep(&stringp
, "@");
1157 if (!ast_strlen_zero(tmp
))
1159 if (!ast_strlen_zero(tmp2
))
1162 if (ast_exists_extension(NULL
, myc
, mye
, 1, NULL
)) {
1163 ast_copy_string(alsa
.exten
, mye
, sizeof(alsa
.exten
));
1164 ast_copy_string(alsa
.context
, myc
, sizeof(alsa
.context
));
1166 alsa_new(&alsa
, AST_STATE_RINGING
);
1168 ast_cli(fd
, "No such extension '%s' in context '%s'\n", mye
, myc
);
1171 ast_mutex_unlock(&alsalock
);
1176 static int console_dial(int fd
, int argc
, char *argv
[])
1178 char tmp
[256], *tmp2
;
1181 int res
= RESULT_SUCCESS
;
1183 if ((argc
!= 2) && (argc
!= 3))
1184 return RESULT_SHOWUSAGE
;
1186 ast_mutex_lock(&alsalock
);
1193 struct ast_frame f
= { AST_FRAME_DTMF
};
1196 ast_queue_frame(alsa
.owner
, &f
);
1199 ast_mutex_unlock(&alsa
.owner
->lock
);
1202 ast_cli(fd
, "You're already in a call. You can use this only to dial digits until you hangup\n");
1203 res
= RESULT_FAILURE
;
1209 char *stringp
= NULL
;
1210 ast_copy_string(tmp
, argv
[2], sizeof(tmp
));
1212 strsep(&stringp
, "@");
1213 tmp2
= strsep(&stringp
, "@");
1214 if (!ast_strlen_zero(tmp
))
1216 if (!ast_strlen_zero(tmp2
))
1219 if (ast_exists_extension(NULL
, myc
, mye
, 1, NULL
)) {
1220 ast_copy_string(alsa
.exten
, mye
, sizeof(alsa
.exten
));
1221 ast_copy_string(alsa
.context
, myc
, sizeof(alsa
.context
));
1223 alsa_new(&alsa
, AST_STATE_RINGING
);
1225 ast_cli(fd
, "No such extension '%s' in context '%s'\n", mye
, myc
);
1228 ast_mutex_unlock(&alsalock
);
1233 static char dial_usage
[] =
1234 "Usage: console dial [extension[@context]]\n"
1235 " Dials a given extension (and context if specified)\n";
1237 static struct ast_cli_entry cli_alsa_answer_deprecated
= {
1239 console_answer_deprecated
, NULL
,
1242 static struct ast_cli_entry cli_alsa_hangup_deprecated
= {
1244 console_hangup_deprecated
, NULL
,
1247 static struct ast_cli_entry cli_alsa_dial_deprecated
= {
1249 console_dial_deprecated
, NULL
,
1252 static struct ast_cli_entry cli_alsa_send_text_deprecated
= {
1253 { "send", "text", NULL
},
1254 console_sendtext_deprecated
, NULL
,
1257 static struct ast_cli_entry cli_alsa_autoanswer_deprecated
= {
1258 { "autoanswer", NULL
},
1259 console_autoanswer_deprecated
, NULL
,
1260 NULL
, autoanswer_complete
};
1262 static struct ast_cli_entry cli_alsa
[] = {
1263 { { "console", "answer", NULL
},
1264 console_answer
, "Answer an incoming console call",
1265 answer_usage
, NULL
, &cli_alsa_answer_deprecated
},
1267 { { "console", "hangup", NULL
},
1268 console_hangup
, "Hangup a call on the console",
1269 hangup_usage
, NULL
, &cli_alsa_hangup_deprecated
},
1271 { { "console", "dial", NULL
},
1272 console_dial
, "Dial an extension on the console",
1273 dial_usage
, NULL
, &cli_alsa_dial_deprecated
},
1275 { { "console", "send", "text", NULL
},
1276 console_sendtext
, "Send text to the remote device",
1277 sendtext_usage
, NULL
, &cli_alsa_send_text_deprecated
},
1279 { { "console", "autoanswer", NULL
},
1280 console_autoanswer
, "Sets/displays autoanswer",
1281 autoanswer_usage
, autoanswer_complete
, &cli_alsa_autoanswer_deprecated
},
1284 static int load_module(void)
1287 struct ast_config
*cfg
;
1288 struct ast_variable
*v
;
1290 /* Copy the default jb config over global_jbconf */
1291 memcpy(&global_jbconf
, &default_jbconf
, sizeof(struct ast_jb_conf
));
1293 strcpy(mohinterpret
, "default");
1295 if ((cfg
= ast_config_load(config
))) {
1296 v
= ast_variable_browse(cfg
, "general");
1297 for (; v
; v
= v
->next
) {
1298 /* handle jb conf */
1299 if (!ast_jb_read_conf(&global_jbconf
, v
->name
, v
->value
))
1302 if (!strcasecmp(v
->name
, "autoanswer"))
1303 autoanswer
= ast_true(v
->value
);
1304 else if (!strcasecmp(v
->name
, "silencesuppression"))
1305 silencesuppression
= ast_true(v
->value
);
1306 else if (!strcasecmp(v
->name
, "silencethreshold"))
1307 silencethreshold
= atoi(v
->value
);
1308 else if (!strcasecmp(v
->name
, "context"))
1309 ast_copy_string(context
, v
->value
, sizeof(context
));
1310 else if (!strcasecmp(v
->name
, "language"))
1311 ast_copy_string(language
, v
->value
, sizeof(language
));
1312 else if (!strcasecmp(v
->name
, "extension"))
1313 ast_copy_string(exten
, v
->value
, sizeof(exten
));
1314 else if (!strcasecmp(v
->name
, "input_device"))
1315 ast_copy_string(indevname
, v
->value
, sizeof(indevname
));
1316 else if (!strcasecmp(v
->name
, "output_device"))
1317 ast_copy_string(outdevname
, v
->value
, sizeof(outdevname
));
1318 else if (!strcasecmp(v
->name
, "mohinterpret"))
1319 ast_copy_string(mohinterpret
, v
->value
, sizeof(mohinterpret
));
1321 ast_config_destroy(cfg
);
1325 ast_log(LOG_ERROR
, "Unable to create pipe\n");
1328 res
= soundcard_init();
1330 if (option_verbose
> 1) {
1331 ast_verbose(VERBOSE_PREFIX_2
"No sound card detected -- console channel will be unavailable\n");
1332 ast_verbose(VERBOSE_PREFIX_2
"Turn off ALSA support by adding 'noload=chan_alsa.so' in /etc/asterisk/modules.conf\n");
1337 res
= ast_channel_register(&alsa_tech
);
1339 ast_log(LOG_ERROR
, "Unable to register channel class 'Console'\n");
1342 ast_cli_register_multiple(cli_alsa
, sizeof(cli_alsa
) / sizeof(struct ast_cli_entry
));
1344 ast_pthread_create_background(&sthread
, NULL
, sound_thread
, NULL
);
1346 if (alsa_monitor_start())
1347 ast_log(LOG_ERROR
, "Problem starting Monitoring\n");
1352 static int unload_module(void)
1354 ast_channel_unregister(&alsa_tech
);
1355 ast_cli_unregister_multiple(cli_alsa
, sizeof(cli_alsa
) / sizeof(struct ast_cli_entry
));
1358 snd_pcm_close(alsa
.icard
);
1360 snd_pcm_close(alsa
.ocard
);
1361 if (sndcmd
[0] > 0) {
1366 ast_softhangup(alsa
.owner
, AST_SOFTHANGUP_APPUNLOAD
);
1372 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY
, "ALSA Console Channel Driver");