mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-02 19:16:15 +00:00
app_meetme is deprecated in 19, to be removed in 21. app_osplookup is deprecated in 19, to be removed in 21. chan_alsa is deprecated in 19, to be removed in 21. chan_mgcp is deprecated in 19, to be removed in 21. chan_skinny is deprecated in 19, to be removed in 21. res_pktccops is deprecated in 19, to be removed in 21. cdr_mysql was deprecated in 1.8, to be removed in 19. app_mysql was deprecated in 1.8, to be removed in 19. app_ices was deprecated in 16, to be removed in 19. app_macro was deprecated in 16, to be removed in 21. app_fax was deprecated in 16, to be removed in 19. app_url was deprecated in 16, to be removed in 19. app_image was deprecated in 16, to be removed in 19. app_nbscat was deprecated in 16, to be removed in 19. app_dahdiras was deprecated in 16, to be removed in 19. cdr_syslog was deprecated in 16, to be removed in 19. chan_oss was deprecated in 16, to be removed in 19. chan_phone was deprecated in 16, to be removed in 19. chan_sip was deprecated in 17, to be removed in 21. chan_nbs was deprecated in 16, to be removed in 19. chan_misdn was deprecated in 16, to be removed in 19. chan_vpb was deprecated in 16, to be removed in 19. res_config_sqlite was deprecated in 16, to be removed in 19. res_monitor was deprecated in 16, to be removed in 21. conf2ael was deprecated in 16, to be removed in 19. muted was deprecated in 16, to be removed in 19. ASTERISK-29548 ASTERISK-29549 ASTERISK-29550 ASTERISK-29551 ASTERISK-29552 ASTERISK-29553 ASTERISK-29554 ASTERISK-29555 ASTERISK-29557 ASTERISK-29558 ASTERISK-29559 ASTERISK-29560 ASTERISK-29561 ASTERISK-29562 ASTERISK-29563 ASTERISK-29564 ASTERISK-29565 ASTERISK-29566 ASTERISK-29567 ASTERISK-29568 ASTERISK-29569 ASTERISK-29570 ASTERISK-29571 ASTERISK-29572 ASTERISK-29573 ASTERISK-29574 Change-Id: Ic3bee31a10d42c4b3bbc913d893f7b2a28a27131
276 lines
7.8 KiB
C
276 lines
7.8 KiB
C
/*
|
|
* Asterisk -- An open source telephony toolkit.
|
|
*
|
|
* Copyright (C) 1999 - 2006, Digium, Inc.
|
|
*
|
|
* Mark Spencer <markster@digium.com>
|
|
*
|
|
* 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 Network broadcast sound support channel driver
|
|
*
|
|
* \author Mark Spencer <markster@digium.com>
|
|
*
|
|
* \ingroup channel_drivers
|
|
*/
|
|
|
|
/*** MODULEINFO
|
|
<depend>nbs</depend>
|
|
<support_level>deprecated</support_level>
|
|
<deprecated_in>16</deprecated_in>
|
|
<removed_in>19</removed_in>
|
|
***/
|
|
|
|
#include "asterisk.h"
|
|
|
|
#include <sys/socket.h>
|
|
#include <sys/time.h>
|
|
#include <arpa/inet.h>
|
|
#include <fcntl.h>
|
|
#include <sys/ioctl.h>
|
|
#include <nbs.h>
|
|
|
|
#include "asterisk/lock.h"
|
|
#include "asterisk/channel.h"
|
|
#include "asterisk/config.h"
|
|
#include "asterisk/module.h"
|
|
#include "asterisk/pbx.h"
|
|
#include "asterisk/utils.h"
|
|
#include "asterisk/format_cache.h"
|
|
|
|
static const char tdesc[] = "Network Broadcast Sound Driver";
|
|
|
|
static char context[AST_MAX_EXTENSION] = "default";
|
|
static const char type[] = "NBS";
|
|
|
|
/* NBS creates private structures on demand */
|
|
|
|
struct nbs_pvt {
|
|
NBS *nbs;
|
|
struct ast_channel *owner; /* Channel we belong to, possibly NULL */
|
|
char app[16]; /* Our app */
|
|
char stream[80]; /* Our stream */
|
|
struct ast_module_user *u; /*! for holding a reference to this module */
|
|
};
|
|
|
|
static struct ast_channel *nbs_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);
|
|
static int nbs_call(struct ast_channel *ast, const char *dest, int timeout);
|
|
static int nbs_hangup(struct ast_channel *ast);
|
|
static struct ast_frame *nbs_xread(struct ast_channel *ast);
|
|
static int nbs_xwrite(struct ast_channel *ast, struct ast_frame *frame);
|
|
|
|
static struct ast_channel_tech nbs_tech = {
|
|
.type = type,
|
|
.description = tdesc,
|
|
.requester = nbs_request,
|
|
.call = nbs_call,
|
|
.hangup = nbs_hangup,
|
|
.read = nbs_xread,
|
|
.write = nbs_xwrite,
|
|
};
|
|
|
|
static int nbs_call(struct ast_channel *ast, const char *dest, int timeout)
|
|
{
|
|
struct nbs_pvt *p;
|
|
|
|
p = ast_channel_tech_pvt(ast);
|
|
|
|
if ((ast_channel_state(ast) != AST_STATE_DOWN) && (ast_channel_state(ast) != AST_STATE_RESERVED)) {
|
|
ast_log(LOG_WARNING, "nbs_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
|
|
return -1;
|
|
}
|
|
/* When we call, it just works, really, there's no destination... Just
|
|
ring the phone and wait for someone to answer */
|
|
ast_debug(1, "Calling %s on %s\n", dest, ast_channel_name(ast));
|
|
|
|
/* If we can't connect, return congestion */
|
|
if (nbs_connect(p->nbs)) {
|
|
ast_log(LOG_WARNING, "NBS Connection failed on %s\n", ast_channel_name(ast));
|
|
ast_queue_control(ast, AST_CONTROL_CONGESTION);
|
|
} else {
|
|
ast_setstate(ast, AST_STATE_RINGING);
|
|
ast_queue_control(ast, AST_CONTROL_ANSWER);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void nbs_destroy(struct nbs_pvt *p)
|
|
{
|
|
if (p->nbs)
|
|
nbs_delstream(p->nbs);
|
|
ast_module_user_remove(p->u);
|
|
ast_free(p);
|
|
}
|
|
|
|
static struct nbs_pvt *nbs_alloc(const char *data)
|
|
{
|
|
struct nbs_pvt *p;
|
|
int flags = 0;
|
|
char stream[256];
|
|
char *opts;
|
|
|
|
ast_copy_string(stream, data, sizeof(stream));
|
|
if ((opts = strchr(stream, ':'))) {
|
|
*opts = '\0';
|
|
opts++;
|
|
} else
|
|
opts = "";
|
|
p = ast_calloc(1, sizeof(*p));
|
|
if (p) {
|
|
if (!ast_strlen_zero(opts)) {
|
|
if (strchr(opts, 'm'))
|
|
flags |= NBS_FLAG_MUTE;
|
|
if (strchr(opts, 'o'))
|
|
flags |= NBS_FLAG_OVERSPEAK;
|
|
if (strchr(opts, 'e'))
|
|
flags |= NBS_FLAG_EMERGENCY;
|
|
if (strchr(opts, 'O'))
|
|
flags |= NBS_FLAG_OVERRIDE;
|
|
} else
|
|
flags = NBS_FLAG_OVERSPEAK;
|
|
|
|
ast_copy_string(p->stream, stream, sizeof(p->stream));
|
|
p->nbs = nbs_newstream("asterisk", stream, flags);
|
|
if (!p->nbs) {
|
|
ast_log(LOG_WARNING, "Unable to allocate new NBS stream '%s' with flags %d\n", stream, flags);
|
|
ast_free(p);
|
|
p = NULL;
|
|
} else {
|
|
/* Set for 8000 hz mono, 640 samples */
|
|
nbs_setbitrate(p->nbs, 8000);
|
|
nbs_setchannels(p->nbs, 1);
|
|
nbs_setblocksize(p->nbs, 640);
|
|
nbs_setblocking(p->nbs, 0);
|
|
}
|
|
}
|
|
return p;
|
|
}
|
|
|
|
static int nbs_hangup(struct ast_channel *ast)
|
|
{
|
|
struct nbs_pvt *p;
|
|
p = ast_channel_tech_pvt(ast);
|
|
ast_debug(1, "nbs_hangup(%s)\n", ast_channel_name(ast));
|
|
if (!ast_channel_tech_pvt(ast)) {
|
|
ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
|
|
return 0;
|
|
}
|
|
nbs_destroy(p);
|
|
ast_channel_tech_pvt_set(ast, NULL);
|
|
ast_setstate(ast, AST_STATE_DOWN);
|
|
return 0;
|
|
}
|
|
|
|
static struct ast_frame *nbs_xread(struct ast_channel *ast)
|
|
{
|
|
ast_debug(1, "Returning null frame on %s\n", ast_channel_name(ast));
|
|
|
|
return &ast_null_frame;
|
|
}
|
|
|
|
static int nbs_xwrite(struct ast_channel *ast, struct ast_frame *frame)
|
|
{
|
|
struct nbs_pvt *p = ast_channel_tech_pvt(ast);
|
|
if (ast_channel_state(ast) != AST_STATE_UP) {
|
|
/* Don't try tos end audio on-hook */
|
|
return 0;
|
|
}
|
|
if (nbs_write(p->nbs, frame->data.ptr, frame->datalen / 2) < 0)
|
|
return -1;
|
|
return 0;
|
|
}
|
|
|
|
static struct ast_channel *nbs_new(struct nbs_pvt *i, int state, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
|
|
{
|
|
struct ast_channel *tmp;
|
|
tmp = ast_channel_alloc(1, state, 0, 0, "", "s", context, assignedids, requestor, 0, "NBS/%s", i->stream);
|
|
if (tmp) {
|
|
ast_channel_tech_set(tmp, &nbs_tech);
|
|
ast_channel_set_fd(tmp, 0, nbs_fd(i->nbs));
|
|
|
|
ast_channel_nativeformats_set(tmp, nbs_tech.capabilities);
|
|
ast_channel_set_rawreadformat(tmp, ast_format_slin);
|
|
ast_channel_set_rawwriteformat(tmp, ast_format_slin);
|
|
ast_channel_set_writeformat(tmp, ast_format_slin);
|
|
ast_channel_set_readformat(tmp, ast_format_slin);
|
|
if (state == AST_STATE_RING)
|
|
ast_channel_rings_set(tmp, 1);
|
|
ast_channel_tech_pvt_set(tmp, i);
|
|
ast_channel_context_set(tmp, context);
|
|
ast_channel_exten_set(tmp, "s");
|
|
ast_channel_language_set(tmp, "");
|
|
i->owner = tmp;
|
|
i->u = ast_module_user_add(tmp);
|
|
ast_channel_unlock(tmp);
|
|
if (state != AST_STATE_DOWN) {
|
|
if (ast_pbx_start(tmp)) {
|
|
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
|
|
ast_hangup(tmp);
|
|
}
|
|
}
|
|
} else
|
|
ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
|
|
return tmp;
|
|
}
|
|
|
|
|
|
static struct ast_channel *nbs_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)
|
|
{
|
|
struct nbs_pvt *p;
|
|
struct ast_channel *tmp = NULL;
|
|
|
|
if (ast_format_cap_iscompatible_format(cap, ast_format_slin) == AST_FORMAT_CMP_NOT_EQUAL) {
|
|
struct ast_str *cap_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
|
|
|
|
ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n",
|
|
ast_format_cap_get_names(cap, &cap_buf));
|
|
return NULL;
|
|
}
|
|
p = nbs_alloc(data);
|
|
if (p) {
|
|
tmp = nbs_new(p, AST_STATE_DOWN, assignedids, requestor);
|
|
if (!tmp)
|
|
nbs_destroy(p);
|
|
}
|
|
return tmp;
|
|
}
|
|
|
|
static int unload_module(void)
|
|
{
|
|
/* First, take us out of the channel loop */
|
|
ast_channel_unregister(&nbs_tech);
|
|
ao2_ref(nbs_tech.capabilities, -1);
|
|
nbs_tech.capabilities = NULL;
|
|
return 0;
|
|
}
|
|
|
|
static int load_module(void)
|
|
{
|
|
if (!(nbs_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
|
|
return AST_MODULE_LOAD_DECLINE;
|
|
}
|
|
ast_format_cap_append(nbs_tech.capabilities, ast_format_slin, 0);
|
|
/* Make sure we can register our channel type */
|
|
if (ast_channel_register(&nbs_tech)) {
|
|
ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
|
|
ao2_ref(nbs_tech.capabilities, -1);
|
|
nbs_tech.capabilities = NULL;
|
|
return AST_MODULE_LOAD_DECLINE;
|
|
}
|
|
return AST_MODULE_LOAD_SUCCESS;
|
|
}
|
|
|
|
AST_MODULE_INFO_STANDARD_DEPRECATED(ASTERISK_GPL_KEY, "Network Broadcast Sound Support");
|