2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 2013 Digium, Inc.
6 * Richard Mudgett <rmudgett@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.
21 * \brief ConfBridge announcer channel driver
23 * \author Richard Mudgett <rmudgett@digium.com>
26 * \arg \ref AstCREDITS
32 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
34 #include "asterisk/channel.h"
35 #include "asterisk/bridging.h"
36 #include "asterisk/core_unreal.h"
37 #include "include/confbridge.h"
39 /* ------------------------------------------------------------------- */
41 /*! ConfBridge announcer channel private. */
43 /*! Unreal channel driver base class values. */
44 struct ast_unreal_pvt base;
45 /*! Conference bridge associated with this announcer. */
46 struct ast_bridge *bridge;
49 static int announce_call(struct ast_channel *chan, const char *addr, int timeout)
51 /* Make sure anyone calling ast_call() for this channel driver is going to fail. */
55 static int announce_hangup(struct ast_channel *ast)
57 struct announce_pvt *p = ast_channel_tech_pvt(ast);
64 /* give the pvt a ref to fulfill calling requirements. */
66 res = ast_unreal_hangup(&p->base, ast);
72 static void announce_pvt_destructor(void *vdoomed)
74 struct announce_pvt *doomed = vdoomed;
76 ao2_cleanup(doomed->bridge);
77 doomed->bridge = NULL;
80 static struct ast_channel *announce_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause)
82 struct ast_channel *chan;
83 const char *conf_name = data;
84 RAII_VAR(struct confbridge_conference *, conference, NULL, ao2_cleanup);
85 RAII_VAR(struct announce_pvt *, pvt, NULL, ao2_cleanup);
87 conference = ao2_find(conference_bridges, conf_name, OBJ_KEY);
91 ast_assert(conference->bridge != NULL);
93 /* Allocate a new private structure and then Asterisk channels */
94 pvt = (struct announce_pvt *) ast_unreal_alloc(sizeof(*pvt), announce_pvt_destructor,
99 ast_set_flag(&pvt->base, AST_UNREAL_NO_OPTIMIZATION);
100 ast_copy_string(pvt->base.name, conf_name, sizeof(pvt->base.name));
101 pvt->bridge = conference->bridge;
102 ao2_ref(pvt->bridge, +1);
104 chan = ast_unreal_new_channels(&pvt->base, conf_announce_get_tech(),
105 AST_STATE_UP, AST_STATE_UP, NULL, NULL, requestor, NULL);
107 ast_answer(pvt->base.owner);
108 ast_answer(pvt->base.chan);
109 if (ast_channel_add_bridge_role(pvt->base.chan, "announcer")) {
118 static struct ast_channel_tech announce_tech = {
120 .description = "Conference Bridge Announcing Channel",
121 .requester = announce_request,
122 .call = announce_call,
123 .hangup = announce_hangup,
125 .send_digit_begin = ast_unreal_digit_begin,
126 .send_digit_end = ast_unreal_digit_end,
127 .read = ast_unreal_read,
128 .write = ast_unreal_write,
129 .write_video = ast_unreal_write,
130 .exception = ast_unreal_read,
131 .indicate = ast_unreal_indicate,
132 .fixup = ast_unreal_fixup,
133 .send_html = ast_unreal_sendhtml,
134 .send_text = ast_unreal_sendtext,
135 .queryoption = ast_unreal_queryoption,
136 .setoption = ast_unreal_setoption,
139 struct ast_channel_tech *conf_announce_get_tech(void)
141 return &announce_tech;
144 void conf_announce_channel_depart(struct ast_channel *chan)
146 struct announce_pvt *p = ast_channel_tech_pvt(chan);
154 if (!ast_test_flag(&p->base, AST_UNREAL_CARETAKER_THREAD)) {
159 ast_clear_flag(&p->base, AST_UNREAL_CARETAKER_THREAD);
162 ast_channel_ref(chan);
167 ast_bridge_depart(chan);
168 ast_channel_unref(chan);
172 int conf_announce_channel_push(struct ast_channel *ast)
174 struct ast_bridge_features *features;
175 struct ast_channel *chan;
176 RAII_VAR(struct announce_pvt *, p, NULL, ao2_cleanup);
179 SCOPED_CHANNELLOCK(lock, ast);
181 p = ast_channel_tech_pvt(ast);
190 ast_channel_ref(chan);
193 features = ast_bridge_features_new();
195 ast_channel_unref(chan);
198 ast_set_flag(&features->feature_flags, AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE);
200 /* Impart the output channel into the bridge */
201 if (ast_bridge_impart(p->bridge, chan, NULL, features, 0)) {
202 ast_bridge_features_destroy(features);
203 ast_channel_unref(chan);
207 ast_set_flag(&p->base, AST_UNREAL_CARETAKER_THREAD);