conf_chan_announce.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 2013 Digium, Inc.
00005  *
00006  * Richard Mudgett <rmudgett@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*!
00020  * \file
00021  * \brief ConfBridge announcer channel driver
00022  *
00023  * \author Richard Mudgett <rmudgett@digium.com>
00024  *
00025  * See Also:
00026  * \arg \ref AstCREDITS
00027  */
00028 
00029 
00030 #include "asterisk.h"
00031 
00032 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 432834 $")
00033 
00034 #include "asterisk/channel.h"
00035 #include "asterisk/bridge.h"
00036 #include "asterisk/core_unreal.h"
00037 #include "include/confbridge.h"
00038 
00039 /* ------------------------------------------------------------------- */
00040 
00041 /*! ConfBridge announcer channel private. */
00042 struct announce_pvt {
00043    /*! Unreal channel driver base class values. */
00044    struct ast_unreal_pvt base;
00045    /*! Conference bridge associated with this announcer. */
00046    struct ast_bridge *bridge;
00047 };
00048 
00049 static int announce_call(struct ast_channel *chan, const char *addr, int timeout)
00050 {
00051    /* Make sure anyone calling ast_call() for this channel driver is going to fail. */
00052    return -1;
00053 }
00054 
00055 static int announce_hangup(struct ast_channel *ast)
00056 {
00057    struct announce_pvt *p = ast_channel_tech_pvt(ast);
00058    int res;
00059 
00060    if (!p) {
00061       return -1;
00062    }
00063 
00064    /* give the pvt a ref to fulfill calling requirements. */
00065    ao2_ref(p, +1);
00066    res = ast_unreal_hangup(&p->base, ast);
00067    ao2_ref(p, -1);
00068 
00069    return res;
00070 }
00071 
00072 static void announce_pvt_destructor(void *vdoomed)
00073 {
00074    struct announce_pvt *doomed = vdoomed;
00075 
00076    ao2_cleanup(doomed->bridge);
00077    doomed->bridge = NULL;
00078    ast_unreal_destructor(&doomed->base);
00079 }
00080 
00081 static struct ast_channel *announce_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)
00082 {
00083    struct ast_channel *chan;
00084    const char *conf_name = data;
00085    RAII_VAR(struct confbridge_conference *, conference, NULL, ao2_cleanup);
00086    RAII_VAR(struct announce_pvt *, pvt, NULL, ao2_cleanup);
00087 
00088    conference = ao2_find(conference_bridges, conf_name, OBJ_KEY);
00089    if (!conference) {
00090       return NULL;
00091    }
00092    ast_assert(conference->bridge != NULL);
00093 
00094    /* Allocate a new private structure and then Asterisk channels */
00095    pvt = (struct announce_pvt *) ast_unreal_alloc(sizeof(*pvt), announce_pvt_destructor,
00096       cap);
00097    if (!pvt) {
00098       return NULL;
00099    }
00100    ast_set_flag(&pvt->base, AST_UNREAL_NO_OPTIMIZATION);
00101    ast_copy_string(pvt->base.name, conf_name, sizeof(pvt->base.name));
00102    pvt->bridge = conference->bridge;
00103    ao2_ref(pvt->bridge, +1);
00104 
00105    chan = ast_unreal_new_channels(&pvt->base, conf_announce_get_tech(),
00106       AST_STATE_UP, AST_STATE_UP, NULL, NULL, assignedids, requestor, 0);
00107    if (chan) {
00108       ast_answer(pvt->base.owner);
00109       ast_answer(pvt->base.chan);
00110       if (ast_channel_add_bridge_role(pvt->base.chan, "announcer")) {
00111          ast_hangup(chan);
00112          chan = NULL;
00113       }
00114    }
00115 
00116    return chan;
00117 }
00118 
00119 static struct ast_channel_tech announce_tech = {
00120    .type = "CBAnn",
00121    .description = "Conference Bridge Announcing Channel",
00122    .requester = announce_request,
00123    .call = announce_call,
00124    .hangup = announce_hangup,
00125 
00126    .send_digit_begin = ast_unreal_digit_begin,
00127    .send_digit_end = ast_unreal_digit_end,
00128    .read = ast_unreal_read,
00129    .write = ast_unreal_write,
00130    .write_video = ast_unreal_write,
00131    .exception = ast_unreal_read,
00132    .indicate = ast_unreal_indicate,
00133    .fixup = ast_unreal_fixup,
00134    .send_html = ast_unreal_sendhtml,
00135    .send_text = ast_unreal_sendtext,
00136    .queryoption = ast_unreal_queryoption,
00137    .setoption = ast_unreal_setoption,
00138    .properties = AST_CHAN_TP_INTERNAL,
00139 };
00140 
00141 struct ast_channel_tech *conf_announce_get_tech(void)
00142 {
00143    return &announce_tech;
00144 }
00145 
00146 void conf_announce_channel_depart(struct ast_channel *chan)
00147 {
00148    struct announce_pvt *p = ast_channel_tech_pvt(chan);
00149 
00150    if (!p) {
00151       return;
00152    }
00153 
00154    ao2_ref(p, +1);
00155    ao2_lock(p);
00156    if (!ast_test_flag(&p->base, AST_UNREAL_CARETAKER_THREAD)) {
00157       ao2_unlock(p);
00158       ao2_ref(p, -1);
00159       return;
00160    }
00161    ast_clear_flag(&p->base, AST_UNREAL_CARETAKER_THREAD);
00162    chan = p->base.chan;
00163    ao2_unlock(p);
00164    ao2_ref(p, -1);
00165    if (chan) {
00166       ast_bridge_depart(chan);
00167       ast_channel_unref(chan);
00168    }
00169 }
00170 
00171 int conf_announce_channel_push(struct ast_channel *ast)
00172 {
00173    struct ast_bridge_features *features;
00174    struct ast_channel *chan;
00175    RAII_VAR(struct announce_pvt *, p, NULL, ao2_cleanup);
00176 
00177    {
00178       SCOPED_CHANNELLOCK(lock, ast);
00179 
00180       p = ast_channel_tech_pvt(ast);
00181       if (!p) {
00182          return -1;
00183       }
00184       ao2_ref(p, +1);
00185       chan = p->base.chan;
00186       if (!chan) {
00187          return -1;
00188       }
00189       ast_channel_ref(chan);
00190    }
00191 
00192    features = ast_bridge_features_new();
00193    if (!features) {
00194       ast_channel_unref(chan);
00195       return -1;
00196    }
00197    ast_set_flag(&features->feature_flags, AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE);
00198 
00199    /* Impart the output channel into the bridge */
00200    if (ast_bridge_impart(p->bridge, chan, NULL, features,
00201       AST_BRIDGE_IMPART_CHAN_DEPARTABLE)) {
00202       ast_bridge_features_destroy(features);
00203       ast_channel_unref(chan);
00204       return -1;
00205    }
00206    ao2_lock(p);
00207    ast_set_flag(&p->base, AST_UNREAL_CARETAKER_THREAD);
00208    ao2_unlock(p);
00209    return 0;
00210 }

Generated on Thu Apr 16 06:27:31 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6