⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chan_oss.c

📁 Asterisk中信道部分的源码 。。。。
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Asterisk -- An open source telephony toolkit. * * Copyright (C) 1999 - 2005, Digium, Inc. * * Mark Spencer <markster@digium.com> * * FreeBSD changes and multiple device support by Luigi Rizzo, 2005.05.25 * note-this code best seen with ts=8 (8-spaces tabs) in the editor * * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. *//*! \file * * \brief Channel driver for OSS sound cards * * \author Mark Spencer <markster@digium.com> * \author Luigi Rizzo * * \par See also * \arg \ref Config_oss * * \ingroup channel_drivers *//*** MODULEINFO	<depend>ossaudio</depend> ***/#include "asterisk.h"ASTERISK_FILE_VERSION(__FILE__, "$Revision: 108796 $")#include <stdio.h>#include <ctype.h>#include <math.h>#include <string.h>#include <unistd.h>#include <sys/ioctl.h>#include <fcntl.h>#include <sys/time.h>#include <stdlib.h>#include <errno.h>#ifdef __linux#include <linux/soundcard.h>#elif defined(__FreeBSD__)#include <sys/soundcard.h>#else#include <soundcard.h>#endif#include "asterisk/lock.h"#include "asterisk/frame.h"#include "asterisk/logger.h"#include "asterisk/callerid.h"#include "asterisk/channel.h"#include "asterisk/module.h"#include "asterisk/options.h"#include "asterisk/pbx.h"#include "asterisk/config.h"#include "asterisk/cli.h"#include "asterisk/utils.h"#include "asterisk/causes.h"#include "asterisk/endian.h"#include "asterisk/stringfields.h"#include "asterisk/abstract_jb.h"#include "asterisk/musiconhold.h"/* ringtones we use */#include "busy.h"#include "ringtone.h"#include "ring10.h"#include "answer.h"/*! Global jitterbuffer configuration - by default, jb is disabled */static struct ast_jb_conf default_jbconf ={	.flags = 0,	.max_size = -1,	.resync_threshold = -1,	.impl = "",};static struct ast_jb_conf global_jbconf;/* * Basic mode of operation: * * we have one keyboard (which receives commands from the keyboard) * and multiple headset's connected to audio cards. * Cards/Headsets are named as the sections of oss.conf. * The section called [general] contains the default parameters. * * At any time, the keyboard is attached to one card, and you * can switch among them using the command 'console foo' * where 'foo' is the name of the card you want. * * oss.conf parameters areSTART_CONFIG[general]    ; General config options, with default values shown.    ; You should use one section per device, with [general] being used    ; for the first device and also as a template for other devices.    ;    ; All but 'debug' can go also in the device-specific sections.    ;    ; debug = 0x0		; misc debug flags, default is 0    ; Set the device to use for I/O    ; device = /dev/dsp    ; Optional mixer command to run upon startup (e.g. to set    ; volume levels, mutes, etc.    ; mixer =    ; Software mic volume booster (or attenuator), useful for sound    ; cards or microphones with poor sensitivity. The volume level    ; is in dB, ranging from -20.0 to +20.0    ; boost = n			; mic volume boost in dB    ; Set the callerid for outgoing calls    ; callerid = John Doe <555-1234>    ; autoanswer = no		; no autoanswer on call    ; autohangup = yes		; hangup when other party closes    ; extension = s		; default extension to call    ; context = default		; default context for outgoing calls    ; language = ""		; default language    ; Default Music on Hold class to use when this channel is placed on hold in    ; the case that the music class is not set on the channel with    ; Set(CHANNEL(musicclass)=whatever) in the dialplan and the peer channel    ; putting this one on hold did not suggest a class to use.    ;    ; mohinterpret=default    ; If you set overridecontext to 'yes', then the whole dial string    ; will be interpreted as an extension, which is extremely useful    ; to dial SIP, IAX and other extensions which use the '@' character.    ; The default is 'no' just for backward compatibility, but the    ; suggestion is to change it.    ; overridecontext = no	; if 'no', the last @ will start the context				; if 'yes' the whole string is an extension.    ; low level device parameters in case you have problems with the    ; device driver on your operating system. You should not touch these    ; unless you know what you are doing.    ; queuesize = 10		; frames in device driver    ; frags = 8			; argument to SETFRAGMENT    ;------------------------------ JITTER BUFFER CONFIGURATION --------------------------    ; jbenable = yes              ; Enables the use of a jitterbuffer on the receiving side of an                                  ; OSS channel. Defaults to "no". An enabled jitterbuffer will                                  ; be used only if the sending side can create and the receiving                                  ; side can not accept jitter. The OSS channel can't accept jitter,                                  ; thus an enabled jitterbuffer on the receive OSS side will always                                  ; be used if the sending side can create jitter.    ; jbmaxsize = 200             ; Max length of the jitterbuffer in milliseconds.    ; jbresyncthreshold = 1000    ; Jump in the frame timestamps over which the jitterbuffer is                                  ; resynchronized. Useful to improve the quality of the voice, with                                  ; big jumps in/broken timestamps, usualy sent from exotic devices                                  ; and programs. Defaults to 1000.    ; jbimpl = fixed              ; Jitterbuffer implementation, used on the receiving side of an OSS                                  ; channel. Two implementations are currenlty available - "fixed"                                  ; (with size always equals to jbmax-size) and "adaptive" (with                                  ; variable size, actually the new jb of IAX2). Defaults to fixed.    ; jblog = no                  ; Enables jitterbuffer frame logging. Defaults to "no".    ;-----------------------------------------------------------------------------------[card1]    ; device = /dev/dsp1	; alternate deviceEND_CONFIG.. and so on for the other cards. *//* * Helper macros to parse config arguments. They will go in a common * header file if their usage is globally accepted. In the meantime, * we define them here. Typical usage is as below. * Remember to open a block right before M_START (as it declares * some variables) and use the M_* macros WITHOUT A SEMICOLON: * *	{ *		M_START(v->name, v->value)  * *		M_BOOL("dothis", x->flag1) *		M_STR("name", x->somestring) *		M_F("bar", some_c_code) *		M_END(some_final_statement) *		... other code in the block *	} * * XXX NOTE these macros should NOT be replicated in other parts of asterisk.  * Likely we will come up with a better way of doing config file parsing. */#define M_START(var, val) \        char *__s = var; char *__val = val;#define M_END(x)   x;#define M_F(tag, f)			if (!strcasecmp((__s), tag)) { f; } else#define M_BOOL(tag, dst)	M_F(tag, (dst) = ast_true(__val) )#define M_UINT(tag, dst)	M_F(tag, (dst) = strtoul(__val, NULL, 0) )#define M_STR(tag, dst)		M_F(tag, ast_copy_string(dst, __val, sizeof(dst)))/* * The following parameters are used in the driver: * *  FRAME_SIZE	the size of an audio frame, in samples. *		160 is used almost universally, so you should not change it. * *  FRAGS	the argument for the SETFRAGMENT ioctl. *		Overridden by the 'frags' parameter in oss.conf * *		Bits 0-7 are the base-2 log of the device's block size, *		bits 16-31 are the number of blocks in the driver's queue. *		There are a lot of differences in the way this parameter *		is supported by different drivers, so you may need to *		experiment a bit with the value. *		A good default for linux is 30 blocks of 64 bytes, which *		results in 6 frames of 320 bytes (160 samples). *		FreeBSD works decently with blocks of 256 or 512 bytes, *		leaving the number unspecified. *		Note that this only refers to the device buffer size, *		this module will then try to keep the lenght of audio *		buffered within small constraints. * *  QUEUE_SIZE	The max number of blocks actually allowed in the device *		driver's buffer, irrespective of the available number. *		Overridden by the 'queuesize' parameter in oss.conf * *		Should be >=2, and at most as large as the hw queue above *		(otherwise it will never be full). */#define FRAME_SIZE	160#define	QUEUE_SIZE	10#if defined(__FreeBSD__)#define	FRAGS	0x8#else#define	FRAGS	( ( (6 * 5) << 16 ) | 0x6 )#endif/* * XXX text message sizes are probably 256 chars, but i am * not sure if there is a suitable definition anywhere. */#define TEXT_SIZE	256#if 0#define	TRYOPEN	1				/* try to open on startup */#endif#define	O_CLOSE	0x444			/* special 'close' mode for device *//* Which device to use */#if defined( __OpenBSD__ ) || defined( __NetBSD__ )#define DEV_DSP "/dev/audio"#else#define DEV_DSP "/dev/dsp"#endif#ifndef MIN#define MIN(a,b) ((a) < (b) ? (a) : (b))#endif#ifndef MAX#define MAX(a,b) ((a) > (b) ? (a) : (b))#endifstatic char *config = "oss.conf";	/* default config file */static int oss_debug;/* * Each sound is made of 'datalen' samples of sound, repeated as needed to * generate 'samplen' samples of data, then followed by 'silencelen' samples * of silence. The loop is repeated if 'repeat' is set. */struct sound {	int ind;	char *desc;	short *data;	int datalen;	int samplen;	int silencelen;	int repeat;};static struct sound sounds[] = {	{ AST_CONTROL_RINGING, "RINGING", ringtone, sizeof(ringtone)/2, 16000, 32000, 1 },	{ AST_CONTROL_BUSY, "BUSY", busy, sizeof(busy)/2, 4000, 4000, 1 },	{ AST_CONTROL_CONGESTION, "CONGESTION", busy, sizeof(busy)/2, 2000, 2000, 1 },	{ AST_CONTROL_RING, "RING10", ring10, sizeof(ring10)/2, 16000, 32000, 1 },	{ AST_CONTROL_ANSWER, "ANSWER", answer, sizeof(answer)/2, 2200, 0, 0 },	{ -1, NULL, 0, 0, 0, 0 },	/* end marker */};/* * descriptor for one of our channels. * There is one used for 'default' values (from the [general] entry in * the configuration file), and then one instance for each device * (the default is cloned from [general], others are only created * if the relevant section exists). */struct chan_oss_pvt {	struct chan_oss_pvt *next;	char *name;	/*	 * cursound indicates which in struct sound we play. -1 means nothing,	 * any other value is a valid sound, in which case sampsent indicates	 * the next sample to send in [0..samplen + silencelen]	 * nosound is set to disable the audio data from the channel	 * (so we can play the tones etc.).	 */	int sndcmd[2];				/* Sound command pipe */	int cursound;				/* index of sound to send */	int sampsent;				/* # of sound samples sent  */	int nosound;				/* set to block audio from the PBX */	int total_blocks;			/* total blocks in the output device */	int sounddev;	enum { M_UNSET, M_FULL, M_READ, M_WRITE } duplex;	int autoanswer;	int autohangup;	int hookstate;	char *mixer_cmd;			/* initial command to issue to the mixer */	unsigned int queuesize;		/* max fragments in queue */	unsigned int frags;			/* parameter for SETFRAGMENT */	int warned;					/* various flags used for warnings */#define WARN_used_blocks	1#define WARN_speed		2#define WARN_frag		4	int w_errors;				/* overfull in the write path */	struct timeval lastopen;	int overridecontext;	int mute;	/* boost support. BOOST_SCALE * 10 ^(BOOST_MAX/20) must	 * be representable in 16 bits to avoid overflows.	 */#define	BOOST_SCALE	(1<<9)#define	BOOST_MAX	40			/* slightly less than 7 bits */	int boost;					/* input boost, scaled by BOOST_SCALE */	char device[64];			/* device to open */	pthread_t sthread;	struct ast_channel *owner;	char ext[AST_MAX_EXTENSION];	char ctx[AST_MAX_CONTEXT];	char language[MAX_LANGUAGE];	char cid_name[256];			/*XXX */	char cid_num[256];			/*XXX */	char mohinterpret[MAX_MUSICCLASS];	/* buffers used in oss_write */	char oss_write_buf[FRAME_SIZE * 2];	int oss_write_dst;	/* buffers used in oss_read - AST_FRIENDLY_OFFSET space for headers	 * plus enough room for a full frame	 */	char oss_read_buf[FRAME_SIZE * 2 + AST_FRIENDLY_OFFSET];	int readpos;				/* read position above */	struct ast_frame read_f;	/* returned by oss_read */};static struct chan_oss_pvt oss_default = {	.cursound = -1,	.sounddev = -1,	.duplex = M_UNSET,			/* XXX check this */	.autoanswer = 1,	.autohangup = 1,	.queuesize = QUEUE_SIZE,	.frags = FRAGS,	.ext = "s",	.ctx = "default",	.readpos = AST_FRIENDLY_OFFSET,	/* start here on reads */	.lastopen = { 0, 0 },	.boost = BOOST_SCALE,};static char *oss_active;	 /* the active device */static int setformat(struct chan_oss_pvt *o, int mode);static struct ast_channel *oss_request(const char *type, int format, void *data, int *cause);static int oss_digit_begin(struct ast_channel *c, char digit);static int oss_digit_end(struct ast_channel *c, char digit, unsigned int duration);static int oss_text(struct ast_channel *c, const char *text);static int oss_hangup(struct ast_channel *c);static int oss_answer(struct ast_channel *c);static struct ast_frame *oss_read(struct ast_channel *chan);static int oss_call(struct ast_channel *c, char *dest, int timeout);static int oss_write(struct ast_channel *chan, struct ast_frame *f);static int oss_indicate(struct ast_channel *chan, int cond, const void *data, size_t datalen);static int oss_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);static char tdesc[] = "OSS Console Channel Driver";static const struct ast_channel_tech oss_tech = {	.type = "Console",	.description = tdesc,	.capabilities = AST_FORMAT_SLINEAR,	.requester = oss_request,	.send_digit_begin = oss_digit_begin,	.send_digit_end = oss_digit_end,	.send_text = oss_text,	.hangup = oss_hangup,	.answer = oss_answer,	.read = oss_read,	.call = oss_call,	.write = oss_write,	.indicate = oss_indicate,	.fixup = oss_fixup,};/* * returns a pointer to the descriptor with the given name */static struct chan_oss_pvt *find_desc(char *dev){	struct chan_oss_pvt *o = NULL;	if (!dev)		ast_log(LOG_WARNING, "null dev\n");	for (o = oss_default.next; o && o->name && dev && strcmp(o->name, dev) != 0; o = o->next);	if (!o)		ast_log(LOG_WARNING, "could not find <%s>\n", dev ? dev : "--no-device--");	return o;}/* * split a string in extension-context, returns pointers to malloc'ed * strings. * If we do not have 'overridecontext' then the last @ is considered as * a context separator, and the context is overridden. * This is usually not very necessary as you can play with the dialplan, * and it is nice not to need it because you have '@' in SIP addresses. * Return value is the buffer address. */static char *ast_ext_ctx(const char *src, char **ext, char **ctx){	struct chan_oss_pvt *o = find_desc(oss_active);	if (ext == NULL || ctx == NULL)		return NULL;			/* error */	*ext = *ctx = NULL;	if (src && *src != '\0')		*ext = ast_strdup(src);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -