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 hwparams
= alloca(snd_pcm_hw_params_sizeof());
371 memset(hwparams
, 0, snd_pcm_hw_params_sizeof());
372 snd_pcm_hw_params_any(handle
, hwparams
);
374 err
= snd_pcm_hw_params_set_access(handle
, hwparams
, SND_PCM_ACCESS_RW_INTERLEAVED
);
376 ast_log(LOG_ERROR
, "set_access failed: %s\n", snd_strerror(err
));
378 err
= snd_pcm_hw_params_set_format(handle
, hwparams
, format
);
380 ast_log(LOG_ERROR
, "set_format failed: %s\n", snd_strerror(err
));
382 err
= snd_pcm_hw_params_set_channels(handle
, hwparams
, 1);
384 ast_log(LOG_ERROR
, "set_channels failed: %s\n", snd_strerror(err
));
387 err
= snd_pcm_hw_params_set_rate_near(handle
, hwparams
, &rate
, &direction
);
388 if (rate
!= DESIRED_RATE
)
389 ast_log(LOG_WARNING
, "Rate not correct, requested %d, got %d\n", DESIRED_RATE
, rate
);
392 err
= snd_pcm_hw_params_set_period_size_near(handle
, hwparams
, &period_size
, &direction
);
394 ast_log(LOG_ERROR
, "period_size(%ld frames) is bad: %s\n", period_size
, snd_strerror(err
));
396 ast_log(LOG_DEBUG
, "Period size is %d\n", err
);
398 buffer_size
= 4096 * 2; /* period_size * 16; */
399 err
= snd_pcm_hw_params_set_buffer_size_near(handle
, hwparams
, &buffer_size
);
401 ast_log(LOG_WARNING
, "Problem setting buffer size of %ld: %s\n", buffer_size
, snd_strerror(err
));
403 ast_log(LOG_DEBUG
, "Buffer size is set to %d frames\n", err
);
407 err
= snd_pcm_hw_params_set_periods_min(handle
, hwparams
, &per_min
, &direction
);
409 ast_log(LOG_ERROR
, "periods_min: %s\n", snd_strerror(err
));
411 err
= snd_pcm_hw_params_set_periods_max(handle
, hwparams
, &per_max
, 0);
413 ast_log(LOG_ERROR
, "periods_max: %s\n", snd_strerror(err
));
416 err
= snd_pcm_hw_params(handle
, hwparams
);
418 ast_log(LOG_ERROR
, "Couldn't set the new hw params: %s\n", snd_strerror(err
));
420 swparams
= alloca(snd_pcm_sw_params_sizeof());
421 memset(swparams
, 0, snd_pcm_sw_params_sizeof());
422 snd_pcm_sw_params_current(handle
, swparams
);
425 if (stream
== SND_PCM_STREAM_PLAYBACK
)
426 start_threshold
= period_size
;
430 err
= snd_pcm_sw_params_set_start_threshold(handle
, swparams
, start_threshold
);
432 ast_log(LOG_ERROR
, "start threshold: %s\n", snd_strerror(err
));
436 if (stream
== SND_PCM_STREAM_PLAYBACK
)
437 stop_threshold
= buffer_size
;
439 stop_threshold
= buffer_size
;
441 err
= snd_pcm_sw_params_set_stop_threshold(handle
, swparams
, stop_threshold
);
443 ast_log(LOG_ERROR
, "stop threshold: %s\n", snd_strerror(err
));
446 err
= snd_pcm_sw_params_set_xfer_align(handle
, swparams
, PERIOD_FRAMES
);
448 ast_log(LOG_ERROR
, "Unable to set xfer alignment: %s\n", snd_strerror(err
));
452 err
= snd_pcm_sw_params_set_silence_threshold(handle
, swparams
, silencethreshold
);
454 ast_log(LOG_ERROR
, "Unable to set silence threshold: %s\n", snd_strerror(err
));
456 err
= snd_pcm_sw_params(handle
, swparams
);
458 ast_log(LOG_ERROR
, "sw_params: %s\n", snd_strerror(err
));
460 err
= snd_pcm_poll_descriptors_count(handle
);
462 ast_log(LOG_ERROR
, "Unable to get a poll descriptors count, error is %s\n", snd_strerror(err
));
464 ast_log(LOG_DEBUG
, "Can't handle more than one device\n");
466 snd_pcm_poll_descriptors(handle
, &pfd
, err
);
467 ast_log(LOG_DEBUG
, "Acquired fd %d from the poll descriptor\n", pfd
.fd
);
469 if (stream
== SND_PCM_STREAM_CAPTURE
)
477 static int soundcard_init(void)
479 alsa
.icard
= alsa_card_init(indevname
, SND_PCM_STREAM_CAPTURE
);
480 alsa
.ocard
= alsa_card_init(outdevname
, SND_PCM_STREAM_PLAYBACK
);
482 if (!alsa
.icard
|| !alsa
.ocard
) {
483 ast_log(LOG_ERROR
, "Problem opening alsa I/O devices\n");
490 static int alsa_digit(struct ast_channel
*c
, char digit
, unsigned int duration
)
492 ast_mutex_lock(&alsalock
);
493 ast_verbose(" << Console Received digit %c of duration %u ms >> \n",
495 ast_mutex_unlock(&alsalock
);
499 static int alsa_text(struct ast_channel
*c
, const char *text
)
501 ast_mutex_lock(&alsalock
);
502 ast_verbose(" << Console Received text %s >> \n", text
);
503 ast_mutex_unlock(&alsalock
);
507 static void grab_owner(void)
509 while (alsa
.owner
&& ast_mutex_trylock(&alsa
.owner
->lock
)) {
510 ast_mutex_unlock(&alsalock
);
512 ast_mutex_lock(&alsalock
);
516 static int alsa_call(struct ast_channel
*c
, char *dest
, int timeout
)
519 struct ast_frame f
= { AST_FRAME_CONTROL
};
520 ast_mutex_lock(&alsalock
);
521 ast_verbose(" << Call placed to '%s' on console >> \n", dest
);
523 ast_verbose(" << Auto-answered >> \n");
526 f
.subclass
= AST_CONTROL_ANSWER
;
527 ast_queue_frame(alsa
.owner
, &f
);
528 ast_mutex_unlock(&alsa
.owner
->lock
);
531 ast_verbose(" << Type 'answer' to answer, or use 'autoanswer' for future calls >> \n");
534 f
.subclass
= AST_CONTROL_RINGING
;
535 ast_queue_frame(alsa
.owner
, &f
);
536 ast_mutex_unlock(&alsa
.owner
->lock
);
538 write(sndcmd
[1], &res
, sizeof(res
));
540 snd_pcm_prepare(alsa
.icard
);
541 snd_pcm_start(alsa
.icard
);
542 ast_mutex_unlock(&alsalock
);
546 static void answer_sound(void)
551 write(sndcmd
[1], &res
, sizeof(res
));
555 static int alsa_answer(struct ast_channel
*c
)
557 ast_mutex_lock(&alsalock
);
558 ast_verbose(" << Console call has been answered >> \n");
560 ast_setstate(c
, AST_STATE_UP
);
562 snd_pcm_prepare(alsa
.icard
);
563 snd_pcm_start(alsa
.icard
);
564 ast_mutex_unlock(&alsalock
);
568 static int alsa_hangup(struct ast_channel
*c
)
571 ast_mutex_lock(&alsalock
);
575 ast_verbose(" << Hangup on console >> \n");
576 ast_module_unref(ast_module_info
->self
);
580 /* Congestion noise */
582 write(sndcmd
[1], &res
, sizeof(res
));
585 snd_pcm_drop(alsa
.icard
);
586 ast_mutex_unlock(&alsalock
);
590 static int alsa_write(struct ast_channel
*chan
, struct ast_frame
*f
)
592 static char sizbuf
[8000];
593 static int sizpos
= 0;
597 /* size_t frames = 0; */
598 snd_pcm_state_t state
;
600 /* Immediately return if no sound is enabled */
604 ast_mutex_lock(&alsalock
);
605 /* Stop any currently playing sound */
606 if (cursound
!= -1) {
607 snd_pcm_drop(alsa
.ocard
);
608 snd_pcm_prepare(alsa
.ocard
);
613 /* We have to digest the frame in 160-byte portions */
614 if (f
->datalen
> sizeof(sizbuf
) - sizpos
) {
615 ast_log(LOG_WARNING
, "Frame too large\n");
618 memcpy(sizbuf
+ sizpos
, f
->data
, f
->datalen
);
622 alsa_monitor_write(sizbuf
, len
);
624 state
= snd_pcm_state(alsa
.ocard
);
625 if (state
== SND_PCM_STATE_XRUN
)
626 snd_pcm_prepare(alsa
.ocard
);
627 res
= snd_pcm_writei(alsa
.ocard
, sizbuf
, len
/ 2);
630 ast_log(LOG_DEBUG
, "XRUN write\n");
632 snd_pcm_prepare(alsa
.ocard
);
633 res
= snd_pcm_writei(alsa
.ocard
, sizbuf
, len
/ 2);
634 if (res
!= len
/ 2) {
635 ast_log(LOG_ERROR
, "Write error: %s\n", snd_strerror(res
));
637 } else if (res
< 0) {
638 ast_log(LOG_ERROR
, "Write error %s\n", snd_strerror(res
));
642 if (res
== -ESTRPIPE
)
643 ast_log(LOG_ERROR
, "You've got some big problems\n");
645 ast_log(LOG_NOTICE
, "Error %d on write\n", res
);
648 ast_mutex_unlock(&alsalock
);
655 static struct ast_frame
*alsa_read(struct ast_channel
*chan
)
657 static struct ast_frame f
;
658 static short __buf
[FRAME_SIZE
+ AST_FRIENDLY_OFFSET
/ 2];
660 static int readpos
= 0;
661 static int left
= FRAME_SIZE
;
662 snd_pcm_state_t state
;
666 ast_mutex_lock(&alsalock
);
667 /* Acknowledge any pending cmd */
668 f
.frametype
= AST_FRAME_NULL
;
676 f
.delivery
.tv_sec
= 0;
677 f
.delivery
.tv_usec
= 0;
679 state
= snd_pcm_state(alsa
.icard
);
680 if ((state
!= SND_PCM_STATE_PREPARED
) && (state
!= SND_PCM_STATE_RUNNING
)) {
681 snd_pcm_prepare(alsa
.icard
);
684 buf
= __buf
+ AST_FRIENDLY_OFFSET
/ 2;
686 r
= snd_pcm_readi(alsa
.icard
, buf
+ readpos
, left
);
689 ast_log(LOG_ERROR
, "XRUN read\n");
691 snd_pcm_prepare(alsa
.icard
);
692 } else if (r
== -ESTRPIPE
) {
693 ast_log(LOG_ERROR
, "-ESTRPIPE\n");
694 snd_pcm_prepare(alsa
.icard
);
696 ast_log(LOG_ERROR
, "Read error: %s\n", snd_strerror(r
));
700 /* Update positions */
704 if (readpos
>= FRAME_SIZE
) {
708 if (chan
->_state
!= AST_STATE_UP
) {
709 /* Don't transmit unless it's up */
710 ast_mutex_unlock(&alsalock
);
713 f
.frametype
= AST_FRAME_VOICE
;
714 f
.subclass
= AST_FORMAT_SLINEAR
;
715 f
.samples
= FRAME_SIZE
;
716 f
.datalen
= FRAME_SIZE
* 2;
718 f
.offset
= AST_FRIENDLY_OFFSET
;
722 alsa_monitor_read((char *) buf
, FRAME_SIZE
* 2);
726 ast_mutex_unlock(&alsalock
);
730 static int alsa_fixup(struct ast_channel
*oldchan
, struct ast_channel
*newchan
)
732 struct chan_alsa_pvt
*p
= newchan
->tech_pvt
;
733 ast_mutex_lock(&alsalock
);
735 ast_mutex_unlock(&alsalock
);
739 static int alsa_indicate(struct ast_channel
*chan
, int cond
, const void *data
, size_t datalen
)
743 ast_mutex_lock(&alsalock
);
746 case AST_CONTROL_BUSY
:
749 case AST_CONTROL_CONGESTION
:
752 case AST_CONTROL_RINGING
:
753 case AST_CONTROL_PROGRESS
:
758 case AST_CONTROL_VIDUPDATE
:
761 case AST_CONTROL_HOLD
:
762 ast_verbose(" << Console Has Been Placed on Hold >> \n");
763 ast_moh_start(chan
, data
, mohinterpret
);
765 case AST_CONTROL_UNHOLD
:
766 ast_verbose(" << Console Has Been Retrieved from Hold >> \n");
770 ast_log(LOG_WARNING
, "Don't know how to display condition %d on %s\n", cond
, chan
->name
);
775 write(sndcmd
[1], &res
, sizeof(res
));
777 ast_mutex_unlock(&alsalock
);
782 static struct ast_channel
*alsa_new(struct chan_alsa_pvt
*p
, int state
)
784 struct ast_channel
*tmp
= NULL
;
786 if (!(tmp
= ast_channel_alloc(1, state
, 0, 0, "", p
->exten
, p
->context
, 0, "ALSA/%s", indevname
)))
789 tmp
->tech
= &alsa_tech
;
790 tmp
->fds
[0] = readdev
;
791 tmp
->nativeformats
= AST_FORMAT_SLINEAR
;
792 tmp
->readformat
= AST_FORMAT_SLINEAR
;
793 tmp
->writeformat
= AST_FORMAT_SLINEAR
;
795 if (!ast_strlen_zero(p
->context
))
796 ast_copy_string(tmp
->context
, p
->context
, sizeof(tmp
->context
));
797 if (!ast_strlen_zero(p
->exten
))
798 ast_copy_string(tmp
->exten
, p
->exten
, sizeof(tmp
->exten
));
799 if (!ast_strlen_zero(language
))
800 ast_string_field_set(tmp
, language
, language
);
802 ast_module_ref(ast_module_info
->self
);
803 ast_jb_configure(tmp
, &global_jbconf
);
804 if (state
!= AST_STATE_DOWN
) {
805 if (ast_pbx_start(tmp
)) {
806 ast_log(LOG_WARNING
, "Unable to start PBX on %s\n", tmp
->name
);
815 static struct ast_channel
*alsa_request(const char *type
, int format
, void *data
, int *cause
)
817 int oldformat
= format
;
818 struct ast_channel
*tmp
= NULL
;
820 format
&= AST_FORMAT_SLINEAR
;
822 ast_log(LOG_NOTICE
, "Asked to get a channel of format '%d'\n", oldformat
);
826 ast_mutex_lock(&alsalock
);
829 ast_log(LOG_NOTICE
, "Already have a call on the ALSA channel\n");
830 *cause
= AST_CAUSE_BUSY
;
831 } else if (!(tmp
= alsa_new(&alsa
, AST_STATE_DOWN
)))
832 ast_log(LOG_WARNING
, "Unable to create new ALSA channel\n");
834 ast_mutex_unlock(&alsalock
);
839 static int console_autoanswer_deprecated(int fd
, int argc
, char *argv
[])
841 int res
= RESULT_SUCCESS
;
843 if ((argc
!= 1) && (argc
!= 2))
844 return RESULT_SHOWUSAGE
;
846 ast_mutex_lock(&alsalock
);
849 ast_cli(fd
, "Auto answer is %s.\n", autoanswer
? "on" : "off");
851 if (!strcasecmp(argv
[1], "on"))
853 else if (!strcasecmp(argv
[1], "off"))
856 res
= RESULT_SHOWUSAGE
;
859 ast_mutex_unlock(&alsalock
);
864 static int console_autoanswer(int fd
, int argc
, char *argv
[])
866 int res
= RESULT_SUCCESS
;;
867 if ((argc
!= 2) && (argc
!= 3))
868 return RESULT_SHOWUSAGE
;
869 ast_mutex_lock(&alsalock
);
871 ast_cli(fd
, "Auto answer is %s.\n", autoanswer
? "on" : "off");
873 if (!strcasecmp(argv
[2], "on"))
875 else if (!strcasecmp(argv
[2], "off"))
878 res
= RESULT_SHOWUSAGE
;
880 ast_mutex_unlock(&alsalock
);
884 static char *autoanswer_complete(const char *line
, const char *word
, int pos
, int state
)
887 #define MIN(a,b) ((a) < (b) ? (a) : (b))
891 if (!ast_strlen_zero(word
) && !strncasecmp(word
, "on", MIN(strlen(word
), 2)))
892 return ast_strdup("on");
894 if (!ast_strlen_zero(word
) && !strncasecmp(word
, "off", MIN(strlen(word
), 3)))
895 return ast_strdup("off");
902 static const char autoanswer_usage
[] =
903 "Usage: console autoanswer [on|off]\n"
904 " Enables or disables autoanswer feature. If used without\n"
905 " argument, displays the current on/off status of autoanswer.\n"
906 " The default value of autoanswer is in 'alsa.conf'.\n";
908 static int console_answer_deprecated(int fd
, int argc
, char *argv
[])
910 int res
= RESULT_SUCCESS
;
913 return RESULT_SHOWUSAGE
;
915 ast_mutex_lock(&alsalock
);
918 ast_cli(fd
, "No one is calling us\n");
919 res
= RESULT_FAILURE
;
925 struct ast_frame f
= { AST_FRAME_CONTROL
, AST_CONTROL_ANSWER
};
926 ast_queue_frame(alsa
.owner
, &f
);
927 ast_mutex_unlock(&alsa
.owner
->lock
);
932 snd_pcm_prepare(alsa
.icard
);
933 snd_pcm_start(alsa
.icard
);
935 ast_mutex_unlock(&alsalock
);
937 return RESULT_SUCCESS
;
940 static int console_answer(int fd
, int argc
, char *argv
[])
942 int res
= RESULT_SUCCESS
;
945 return RESULT_SHOWUSAGE
;
947 ast_mutex_lock(&alsalock
);
950 ast_cli(fd
, "No one is calling us\n");
951 res
= RESULT_FAILURE
;
957 struct ast_frame f
= { AST_FRAME_CONTROL
, AST_CONTROL_ANSWER
};
958 ast_queue_frame(alsa
.owner
, &f
);
959 ast_mutex_unlock(&alsa
.owner
->lock
);
964 snd_pcm_prepare(alsa
.icard
);
965 snd_pcm_start(alsa
.icard
);
967 ast_mutex_unlock(&alsalock
);
969 return RESULT_SUCCESS
;
972 static char sendtext_usage
[] =
973 "Usage: console send text <message>\n"
974 " Sends a text message for display on the remote terminal.\n";
976 static int console_sendtext_deprecated(int fd
, int argc
, char *argv
[])
979 int res
= RESULT_SUCCESS
;
982 return RESULT_SHOWUSAGE
;
984 ast_mutex_lock(&alsalock
);
987 ast_cli(fd
, "No one is calling us\n");
988 res
= RESULT_FAILURE
;
990 struct ast_frame f
= { AST_FRAME_TEXT
, 0 };
991 char text2send
[256] = "";
993 while (tmparg
< argc
) {
994 strncat(text2send
, argv
[tmparg
++], sizeof(text2send
) - strlen(text2send
) - 1);
995 strncat(text2send
, " ", sizeof(text2send
) - strlen(text2send
) - 1);
997 text2send
[strlen(text2send
) - 1] = '\n';
999 f
.datalen
= strlen(text2send
) + 1;
1002 ast_queue_frame(alsa
.owner
, &f
);
1003 f
.frametype
= AST_FRAME_CONTROL
;
1004 f
.subclass
= AST_CONTROL_ANSWER
;
1007 ast_queue_frame(alsa
.owner
, &f
);
1008 ast_mutex_unlock(&alsa
.owner
->lock
);
1012 ast_mutex_unlock(&alsalock
);
1017 static int console_sendtext(int fd
, int argc
, char *argv
[])
1020 int res
= RESULT_SUCCESS
;
1023 return RESULT_SHOWUSAGE
;
1025 ast_mutex_lock(&alsalock
);
1028 ast_cli(fd
, "No one is calling us\n");
1029 res
= RESULT_FAILURE
;
1031 struct ast_frame f
= { AST_FRAME_TEXT
, 0 };
1032 char text2send
[256] = "";
1033 text2send
[0] = '\0';
1034 while (tmparg
< argc
) {
1035 strncat(text2send
, argv
[tmparg
++], sizeof(text2send
) - strlen(text2send
) - 1);
1036 strncat(text2send
, " ", sizeof(text2send
) - strlen(text2send
) - 1);
1038 text2send
[strlen(text2send
) - 1] = '\n';
1040 f
.datalen
= strlen(text2send
) + 1;
1043 ast_queue_frame(alsa
.owner
, &f
);
1044 f
.frametype
= AST_FRAME_CONTROL
;
1045 f
.subclass
= AST_CONTROL_ANSWER
;
1048 ast_queue_frame(alsa
.owner
, &f
);
1049 ast_mutex_unlock(&alsa
.owner
->lock
);
1053 ast_mutex_unlock(&alsalock
);
1058 static char answer_usage
[] =
1059 "Usage: console answer\n"
1060 " Answers an incoming call on the console (ALSA) channel.\n";
1062 static int console_hangup_deprecated(int fd
, int argc
, char *argv
[])
1064 int res
= RESULT_SUCCESS
;
1067 return RESULT_SHOWUSAGE
;
1071 ast_mutex_lock(&alsalock
);
1073 if (!alsa
.owner
&& !hookstate
) {
1074 ast_cli(fd
, "No call to hangup up\n");
1075 res
= RESULT_FAILURE
;
1080 ast_queue_hangup(alsa
.owner
);
1081 ast_mutex_unlock(&alsa
.owner
->lock
);
1085 ast_mutex_unlock(&alsalock
);
1090 static int console_hangup(int fd
, int argc
, char *argv
[])
1092 int res
= RESULT_SUCCESS
;
1095 return RESULT_SHOWUSAGE
;
1099 ast_mutex_lock(&alsalock
);
1101 if (!alsa
.owner
&& !hookstate
) {
1102 ast_cli(fd
, "No call to hangup up\n");
1103 res
= RESULT_FAILURE
;
1108 ast_queue_hangup(alsa
.owner
);
1109 ast_mutex_unlock(&alsa
.owner
->lock
);
1113 ast_mutex_unlock(&alsalock
);
1118 static char hangup_usage
[] =
1119 "Usage: console hangup\n"
1120 " Hangs up any call currently placed on the console.\n";
1122 static int console_dial_deprecated(int fd
, int argc
, char *argv
[])
1124 char tmp
[256], *tmp2
;
1127 int res
= RESULT_SUCCESS
;
1129 if ((argc
!= 1) && (argc
!= 2))
1130 return RESULT_SHOWUSAGE
;
1132 ast_mutex_lock(&alsalock
);
1139 struct ast_frame f
= { AST_FRAME_DTMF
};
1142 ast_queue_frame(alsa
.owner
, &f
);
1145 ast_mutex_unlock(&alsa
.owner
->lock
);
1148 ast_cli(fd
, "You're already in a call. You can use this only to dial digits until you hangup\n");
1149 res
= RESULT_FAILURE
;
1155 char *stringp
= NULL
;
1156 ast_copy_string(tmp
, argv
[1], sizeof(tmp
));
1158 strsep(&stringp
, "@");
1159 tmp2
= strsep(&stringp
, "@");
1160 if (!ast_strlen_zero(tmp
))
1162 if (!ast_strlen_zero(tmp2
))
1165 if (ast_exists_extension(NULL
, myc
, mye
, 1, NULL
)) {
1166 ast_copy_string(alsa
.exten
, mye
, sizeof(alsa
.exten
));
1167 ast_copy_string(alsa
.context
, myc
, sizeof(alsa
.context
));
1169 alsa_new(&alsa
, AST_STATE_RINGING
);
1171 ast_cli(fd
, "No such extension '%s' in context '%s'\n", mye
, myc
);
1174 ast_mutex_unlock(&alsalock
);
1179 static int console_dial(int fd
, int argc
, char *argv
[])
1181 char tmp
[256], *tmp2
;
1184 int res
= RESULT_SUCCESS
;
1186 if ((argc
!= 2) && (argc
!= 3))
1187 return RESULT_SHOWUSAGE
;
1189 ast_mutex_lock(&alsalock
);
1196 struct ast_frame f
= { AST_FRAME_DTMF
};
1199 ast_queue_frame(alsa
.owner
, &f
);
1202 ast_mutex_unlock(&alsa
.owner
->lock
);
1205 ast_cli(fd
, "You're already in a call. You can use this only to dial digits until you hangup\n");
1206 res
= RESULT_FAILURE
;
1212 char *stringp
= NULL
;
1213 ast_copy_string(tmp
, argv
[2], sizeof(tmp
));
1215 strsep(&stringp
, "@");
1216 tmp2
= strsep(&stringp
, "@");
1217 if (!ast_strlen_zero(tmp
))
1219 if (!ast_strlen_zero(tmp2
))
1222 if (ast_exists_extension(NULL
, myc
, mye
, 1, NULL
)) {
1223 ast_copy_string(alsa
.exten
, mye
, sizeof(alsa
.exten
));
1224 ast_copy_string(alsa
.context
, myc
, sizeof(alsa
.context
));
1226 alsa_new(&alsa
, AST_STATE_RINGING
);
1228 ast_cli(fd
, "No such extension '%s' in context '%s'\n", mye
, myc
);
1231 ast_mutex_unlock(&alsalock
);
1236 static char dial_usage
[] =
1237 "Usage: console dial [extension[@context]]\n"
1238 " Dials a given extension (and context if specified)\n";
1240 static struct ast_cli_entry cli_alsa_answer_deprecated
= {
1242 console_answer_deprecated
, NULL
,
1245 static struct ast_cli_entry cli_alsa_hangup_deprecated
= {
1247 console_hangup_deprecated
, NULL
,
1250 static struct ast_cli_entry cli_alsa_dial_deprecated
= {
1252 console_dial_deprecated
, NULL
,
1255 static struct ast_cli_entry cli_alsa_send_text_deprecated
= {
1256 { "send", "text", NULL
},
1257 console_sendtext_deprecated
, NULL
,
1260 static struct ast_cli_entry cli_alsa_autoanswer_deprecated
= {
1261 { "autoanswer", NULL
},
1262 console_autoanswer_deprecated
, NULL
,
1263 NULL
, autoanswer_complete
};
1265 static struct ast_cli_entry cli_alsa
[] = {
1266 { { "console", "answer", NULL
},
1267 console_answer
, "Answer an incoming console call",
1268 answer_usage
, NULL
, &cli_alsa_answer_deprecated
},
1270 { { "console", "hangup", NULL
},
1271 console_hangup
, "Hangup a call on the console",
1272 hangup_usage
, NULL
, &cli_alsa_hangup_deprecated
},
1274 { { "console", "dial", NULL
},
1275 console_dial
, "Dial an extension on the console",
1276 dial_usage
, NULL
, &cli_alsa_dial_deprecated
},
1278 { { "console", "send", "text", NULL
},
1279 console_sendtext
, "Send text to the remote device",
1280 sendtext_usage
, NULL
, &cli_alsa_send_text_deprecated
},
1282 { { "console", "autoanswer", NULL
},
1283 console_autoanswer
, "Sets/displays autoanswer",
1284 autoanswer_usage
, autoanswer_complete
, &cli_alsa_autoanswer_deprecated
},
1287 static int load_module(void)
1290 struct ast_config
*cfg
;
1291 struct ast_variable
*v
;
1293 /* Copy the default jb config over global_jbconf */
1294 memcpy(&global_jbconf
, &default_jbconf
, sizeof(struct ast_jb_conf
));
1296 strcpy(mohinterpret
, "default");
1298 if ((cfg
= ast_config_load(config
))) {
1299 v
= ast_variable_browse(cfg
, "general");
1300 for (; v
; v
= v
->next
) {
1301 /* handle jb conf */
1302 if (!ast_jb_read_conf(&global_jbconf
, v
->name
, v
->value
))
1305 if (!strcasecmp(v
->name
, "autoanswer"))
1306 autoanswer
= ast_true(v
->value
);
1307 else if (!strcasecmp(v
->name
, "silencesuppression"))
1308 silencesuppression
= ast_true(v
->value
);
1309 else if (!strcasecmp(v
->name
, "silencethreshold"))
1310 silencethreshold
= atoi(v
->value
);
1311 else if (!strcasecmp(v
->name
, "context"))
1312 ast_copy_string(context
, v
->value
, sizeof(context
));
1313 else if (!strcasecmp(v
->name
, "language"))
1314 ast_copy_string(language
, v
->value
, sizeof(language
));
1315 else if (!strcasecmp(v
->name
, "extension"))
1316 ast_copy_string(exten
, v
->value
, sizeof(exten
));
1317 else if (!strcasecmp(v
->name
, "input_device"))
1318 ast_copy_string(indevname
, v
->value
, sizeof(indevname
));
1319 else if (!strcasecmp(v
->name
, "output_device"))
1320 ast_copy_string(outdevname
, v
->value
, sizeof(outdevname
));
1321 else if (!strcasecmp(v
->name
, "mohinterpret"))
1322 ast_copy_string(mohinterpret
, v
->value
, sizeof(mohinterpret
));
1324 ast_config_destroy(cfg
);
1328 ast_log(LOG_ERROR
, "Unable to create pipe\n");
1331 res
= soundcard_init();
1333 if (option_verbose
> 1) {
1334 ast_verbose(VERBOSE_PREFIX_2
"No sound card detected -- console channel will be unavailable\n");
1335 ast_verbose(VERBOSE_PREFIX_2
"Turn off ALSA support by adding 'noload=chan_alsa.so' in /etc/asterisk/modules.conf\n");
1340 res
= ast_channel_register(&alsa_tech
);
1342 ast_log(LOG_ERROR
, "Unable to register channel class 'Console'\n");
1345 ast_cli_register_multiple(cli_alsa
, sizeof(cli_alsa
) / sizeof(struct ast_cli_entry
));
1347 ast_pthread_create_background(&sthread
, NULL
, sound_thread
, NULL
);
1349 if (alsa_monitor_start())
1350 ast_log(LOG_ERROR
, "Problem starting Monitoring\n");
1355 static int unload_module(void)
1357 ast_channel_unregister(&alsa_tech
);
1358 ast_cli_unregister_multiple(cli_alsa
, sizeof(cli_alsa
) / sizeof(struct ast_cli_entry
));
1361 snd_pcm_close(alsa
.icard
);
1363 snd_pcm_close(alsa
.ocard
);
1364 if (sndcmd
[0] > 0) {
1369 ast_softhangup(alsa
.owner
, AST_SOFTHANGUP_APPUNLOAD
);
1375 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY
, "ALSA Console Channel Driver");