stasic.c: Fix printf format type mismatches with arguments.
[asterisk/asterisk.git] / channels / chan_bridge_media.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013 Digium, Inc.
5  *
6  * Jonathan Rose <jrose@digium.com>
7  *
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.
13  *
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.
17  */
18
19 /*!
20  * \file
21  * \brief Bridge Media Channels driver
22  *
23  * \author Jonathan Rose <jrose@digium.com>
24  * \author Richard Mudgett <rmudgett@digium.com>
25  *
26  * \brief Bridge Media Channels
27  *
28  * \ingroup channel_drivers
29  */
30
31 /*** MODULEINFO
32         <support_level>core</support_level>
33  ***/
34
35 #include "asterisk.h"
36
37 #include "asterisk/channel.h"
38 #include "asterisk/bridge.h"
39 #include "asterisk/core_unreal.h"
40 #include "asterisk/module.h"
41
42 static int media_call(struct ast_channel *chan, const char *addr, int timeout)
43 {
44         /* ast_call() will fail unconditionally against channels provided by this driver */
45         return -1;
46 }
47
48 static int media_hangup(struct ast_channel *ast)
49 {
50         struct ast_unreal_pvt *p = ast_channel_tech_pvt(ast);
51         int res;
52
53         if (!p) {
54                 return -1;
55         }
56
57         /* Give the pvt a ref to fulfill calling requirements. */
58         ao2_ref(p, +1);
59         res = ast_unreal_hangup(p, ast);
60         ao2_ref(p, -1);
61
62         return res;
63 }
64
65 static struct ast_channel *announce_request(const char *type, struct ast_format_cap *cap,
66         const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause);
67
68 static struct ast_channel *record_request(const char *type, struct ast_format_cap *cap,
69         const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause);
70
71 static struct ast_channel_tech announce_tech = {
72         .type = "Announcer",
73         .description = "Bridge Media Announcing Channel Driver",
74         .requester = announce_request,
75         .call = media_call,
76         .hangup = media_hangup,
77
78         .send_digit_begin = ast_unreal_digit_begin,
79         .send_digit_end = ast_unreal_digit_end,
80         .read = ast_unreal_read,
81         .write = ast_unreal_write,
82         .write_video = ast_unreal_write,
83         .exception = ast_unreal_read,
84         .indicate = ast_unreal_indicate,
85         .fixup = ast_unreal_fixup,
86         .send_html = ast_unreal_sendhtml,
87         .send_text = ast_unreal_sendtext,
88         .queryoption = ast_unreal_queryoption,
89         .setoption = ast_unreal_setoption,
90         .properties = AST_CHAN_TP_INTERNAL,
91 };
92
93 static struct ast_channel_tech record_tech = {
94         .type = "Recorder",
95         .description = "Bridge Media Recording Channel Driver",
96         .requester = record_request,
97         .call = media_call,
98         .hangup = media_hangup,
99
100         .send_digit_begin = ast_unreal_digit_begin,
101         .send_digit_end = ast_unreal_digit_end,
102         .read = ast_unreal_read,
103         .write = ast_unreal_write,
104         .write_video = ast_unreal_write,
105         .exception = ast_unreal_read,
106         .indicate = ast_unreal_indicate,
107         .fixup = ast_unreal_fixup,
108         .send_html = ast_unreal_sendhtml,
109         .send_text = ast_unreal_sendtext,
110         .queryoption = ast_unreal_queryoption,
111         .setoption = ast_unreal_setoption,
112         .properties = AST_CHAN_TP_INTERNAL,
113 };
114
115 static struct ast_channel *media_request_helper(struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids,
116         const struct ast_channel *requestor, const char *data, struct ast_channel_tech *tech, const char *role)
117 {
118         struct ast_channel *chan;
119         ast_callid callid;
120
121         RAII_VAR(struct ast_unreal_pvt *, pvt, NULL, ao2_cleanup);
122
123         if (!(pvt = ast_unreal_alloc(sizeof(*pvt), ast_unreal_destructor, cap))) {
124                 return NULL;
125         }
126
127         ast_copy_string(pvt->name, data, sizeof(pvt->name));
128
129         ast_set_flag(pvt, AST_UNREAL_NO_OPTIMIZATION);
130
131         callid = ast_read_threadstorage_callid();
132
133         chan = ast_unreal_new_channels(pvt, tech,
134                 AST_STATE_UP, AST_STATE_UP, NULL, NULL, assignedids, requestor, callid);
135         if (!chan) {
136                 return NULL;
137         }
138
139         ast_answer(pvt->owner);
140         ast_answer(pvt->chan);
141
142         if (ast_channel_add_bridge_role(pvt->chan, role)) {
143                 ast_hangup(chan);
144                 return NULL;
145         }
146
147         return chan;
148 }
149
150 static struct ast_channel *announce_request(const char *type, struct ast_format_cap *cap,
151         const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
152 {
153         return media_request_helper(cap, assignedids, requestor, data, &announce_tech, "announcer");
154 }
155
156 static struct ast_channel *record_request(const char *type, struct ast_format_cap *cap,
157         const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
158 {
159         return media_request_helper(cap, assignedids, requestor, data, &record_tech, "recorder");
160 }
161
162 static void cleanup_capabilities(void)
163 {
164         if (announce_tech.capabilities) {
165                 ao2_ref(announce_tech.capabilities, -1);
166                 announce_tech.capabilities = NULL;
167         }
168
169         if (record_tech.capabilities) {
170                 ao2_ref(record_tech.capabilities, -1);
171                 record_tech.capabilities = NULL;
172         }
173 }
174
175 static int unload_module(void)
176 {
177         ast_channel_unregister(&announce_tech);
178         ast_channel_unregister(&record_tech);
179         cleanup_capabilities();
180         return 0;
181 }
182
183 static int load_module(void)
184 {
185         announce_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
186         if (!announce_tech.capabilities) {
187                 return AST_MODULE_LOAD_DECLINE;
188         }
189
190         record_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
191         if (!record_tech.capabilities) {
192                 return AST_MODULE_LOAD_DECLINE;
193         }
194
195         ast_format_cap_append_by_type(announce_tech.capabilities, AST_MEDIA_TYPE_UNKNOWN);
196         ast_format_cap_append_by_type(record_tech.capabilities, AST_MEDIA_TYPE_UNKNOWN);
197
198         if (ast_channel_register(&announce_tech)) {
199                 ast_log(LOG_ERROR, "Unable to register channel technology %s(%s).\n",
200                         announce_tech.type, announce_tech.description);
201                 cleanup_capabilities();
202                 return AST_MODULE_LOAD_DECLINE;
203         }
204
205         if (ast_channel_register(&record_tech)) {
206                 ast_log(LOG_ERROR, "Unable to register channel technology %s(%s).\n",
207                         record_tech.type, record_tech.description);
208                 cleanup_capabilities();
209                 return AST_MODULE_LOAD_DECLINE;
210         }
211
212         return AST_MODULE_LOAD_SUCCESS;
213 }
214
215 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Bridge Media Channel Driver",
216         .support_level = AST_MODULE_SUPPORT_CORE,
217         .load = load_module,
218         .unload = unload_module,
219 );