A great big renaming patch
[asterisk/asterisk.git] / apps / confbridge / confbridge_manager.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 /*! \file
20  *
21  * \brief Confbridge manager events for stasis messages
22  *
23  * \author Jonathan Rose <jrose@digium.com>
24  */
25
26 #include "asterisk.h"
27
28 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
29
30 #include "asterisk/channel.h"
31 #include "asterisk/bridge.h"
32 #include "asterisk/stasis.h"
33 #include "asterisk/stasis_channels.h"
34 #include "asterisk/stasis_bridges.h"
35 #include "asterisk/manager.h"
36 #include "asterisk/stasis_message_router.h"
37 #include "include/confbridge.h"
38
39 /*** DOCUMENTATION
40         <managerEvent language="en_US" name="ConfbridgeStart">
41                 <managerEventInstance class="EVENT_FLAG_CALL">
42                         <synopsis>Raised when a conference starts.</synopsis>
43                         <syntax>
44                                 <parameter name="Conference">
45                                         <para>The name of the Confbridge conference.</para>
46                                 </parameter>
47                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='BridgeCreate']/managerEventInstance/syntax/parameter)" />
48                         </syntax>
49                         <see-also>
50                                 <ref type="managerEvent">ConfbridgeEnd</ref>
51                                 <ref type="application">ConfBridge</ref>
52                         </see-also>
53                 </managerEventInstance>
54         </managerEvent>
55         <managerEvent language="en_US" name="ConfbridgeEnd">
56                 <managerEventInstance class="EVENT_FLAG_CALL">
57                         <synopsis>Raised when a conference ends.</synopsis>
58                         <syntax>
59                                 <parameter name="Conference">
60                                         <para>The name of the Confbridge conference.</para>
61                                 </parameter>
62                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='BridgeCreate']/managerEventInstance/syntax/parameter)" />
63                         </syntax>
64                         <see-also>
65                                 <ref type="managerEvent">ConfbridgeStart</ref>
66                                 <ref type="application">ConfBridge</ref>
67                         </see-also>
68                 </managerEventInstance>
69         </managerEvent>
70         <managerEvent language="en_US" name="ConfbridgeJoin">
71                 <managerEventInstance class="EVENT_FLAG_CALL">
72                         <synopsis>Raised when a channel joins a Confbridge conference.</synopsis>
73                         <syntax>
74                                 <parameter name="Conference">
75                                         <para>The name of the Confbridge conference.</para>
76                                 </parameter>
77                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='BridgeCreate']/managerEventInstance/syntax/parameter)" />
78                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
79                         </syntax>
80                         <see-also>
81                                 <ref type="managerEvent">ConfbridgeLeave</ref>
82                                 <ref type="application">ConfBridge</ref>
83                         </see-also>
84                 </managerEventInstance>
85         </managerEvent>
86         <managerEvent language="en_US" name="ConfbridgeLeave">
87                 <managerEventInstance class="EVENT_FLAG_CALL">
88                         <synopsis>Raised when a channel leaves a Confbridge conference.</synopsis>
89                         <syntax>
90                                 <parameter name="Conference">
91                                         <para>The name of the Confbridge conference.</para>
92                                 </parameter>
93                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='BridgeCreate']/managerEventInstance/syntax/parameter)" />
94                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
95                         </syntax>
96                         <see-also>
97                                 <ref type="managerEvent">ConfbridgeJoin</ref>
98                                 <ref type="application">ConfBridge</ref>
99                         </see-also>
100                 </managerEventInstance>
101         </managerEvent>
102         <managerEvent language="en_US" name="ConfbridgeRecord">
103                 <managerEventInstance class="EVENT_FLAG_CALL">
104                         <synopsis>Raised when a conference starts recording.</synopsis>
105                         <syntax>
106                                 <parameter name="Conference">
107                                         <para>The name of the Confbridge conference.</para>
108                                 </parameter>
109                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='BridgeCreate']/managerEventInstance/syntax/parameter)" />
110                         </syntax>
111                         <see-also>
112                                 <ref type="managerEvent">ConfbridgeStopRecord</ref>
113                                 <ref type="application">ConfBridge</ref>
114                         </see-also>
115                 </managerEventInstance>
116         </managerEvent>
117         <managerEvent language="en_US" name="ConfbridgeStopRecord">
118                 <managerEventInstance class="EVENT_FLAG_CALL">
119                         <synopsis>Raised when a conference that was recording stops recording.</synopsis>
120                         <syntax>
121                                 <parameter name="Conference">
122                                         <para>The name of the Confbridge conference.</para>
123                                 </parameter>
124                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='BridgeCreate']/managerEventInstance/syntax/parameter)" />
125                         </syntax>
126                         <see-also>
127                                 <ref type="managerEvent">ConfbridgeRecord</ref>
128                                 <ref type="application">ConfBridge</ref>
129                         </see-also>
130                 </managerEventInstance>
131         </managerEvent>
132         <managerEvent language="en_US" name="ConfbridgeMute">
133                 <managerEventInstance class="EVENT_FLAG_CALL">
134                         <synopsis>Raised when a Confbridge participant mutes.</synopsis>
135                         <syntax>
136                                 <parameter name="Conference">
137                                         <para>The name of the Confbridge conference.</para>
138                                 </parameter>
139                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='BridgeCreate']/managerEventInstance/syntax/parameter)" />
140                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
141                         </syntax>
142                         <see-also>
143                                 <ref type="managerEvent">ConfbridgeUnmute</ref>
144                                 <ref type="application">ConfBridge</ref>
145                         </see-also>
146                 </managerEventInstance>
147         </managerEvent>
148         <managerEvent language="en_US" name="ConfbridgeUnmute">
149                 <managerEventInstance class="EVENT_FLAG_CALL">
150                         <synopsis>Raised when a confbridge participant unmutes.</synopsis>
151                         <syntax>
152                                 <parameter name="Conference">
153                                         <para>The name of the Confbridge conference.</para>
154                                 </parameter>
155                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='BridgeCreate']/managerEventInstance/syntax/parameter)" />
156                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
157                         </syntax>
158                         <see-also>
159                                 <ref type="managerEvent">ConfbridgeMute</ref>
160                                 <ref type="application">ConfBridge</ref>
161                         </see-also>
162                 </managerEventInstance>
163         </managerEvent>
164
165         <managerEvent language="en_US" name="ConfbridgeTalking">
166                 <managerEventInstance class="EVENT_FLAG_CALL">
167                         <synopsis>Raised when a confbridge participant unmutes.</synopsis>
168                         <syntax>
169                                 <parameter name="Conference">
170                                         <para>The name of the Confbridge conference.</para>
171                                 </parameter>
172                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='BridgeCreate']/managerEventInstance/syntax/parameter)" />
173                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
174                                 <parameter name="TalkingStatus">
175                                         <enumlist>
176                                                 <enum name="on"/>
177                                                 <enum name="off"/>
178                                         </enumlist>
179                                 </parameter>
180                         </syntax>
181                         <see-also>
182                                 <ref type="application">ConfBridge</ref>
183                         </see-also>
184                 </managerEventInstance>
185         </managerEvent>
186 ***/
187
188 static struct stasis_message_router *bridge_state_router;
189 static struct stasis_message_router *channel_state_router;
190
191 static void confbridge_publish_manager_event(
192         struct stasis_message *message,
193         const char *event,
194         struct ast_str *extra_text)
195 {
196         struct ast_bridge_blob *blob = stasis_message_data(message);
197         const char *conference_name;
198         RAII_VAR(struct ast_str *, bridge_text, NULL, ast_free);
199         RAII_VAR(struct ast_str *, channel_text, NULL, ast_free);
200
201         ast_assert(blob != NULL);
202         ast_assert(event != NULL);
203
204         bridge_text = ast_manager_build_bridge_state_string(blob->bridge, "");
205         if (!bridge_text) {
206                 return;
207         }
208
209         conference_name = ast_json_string_get(ast_json_object_get(blob->blob, "conference"));
210         ast_assert(conference_name != NULL);
211
212         if (blob->channel) {
213                 channel_text = ast_manager_build_channel_state_string(blob->channel);
214         }
215
216         manager_event(EVENT_FLAG_CALL, event,
217                 "Conference: %s\r\n"
218                 "%s"
219                 "%s"
220                 "%s",
221                 conference_name,
222                 ast_str_buffer(bridge_text),
223                 S_COR(channel_text, ast_str_buffer(channel_text), ""),
224                 S_COR(extra_text, ast_str_buffer(extra_text), ""));
225 }
226
227 static void confbridge_start_cb(void *data, struct stasis_subscription *sub,
228         struct stasis_topic *topic,
229         struct stasis_message *message)
230 {
231         confbridge_publish_manager_event(message, "ConfbridgeStart", NULL);
232 }
233
234 static void confbridge_end_cb(void *data, struct stasis_subscription *sub,
235         struct stasis_topic *topic,
236         struct stasis_message *message)
237 {
238         confbridge_publish_manager_event(message, "ConfbridgeEnd", NULL);
239 }
240
241 static void confbridge_leave_cb(void *data, struct stasis_subscription *sub,
242         struct stasis_topic *topic,
243         struct stasis_message *message)
244 {
245         confbridge_publish_manager_event(message, "ConfbridgeLeave", NULL);
246 }
247
248 static void confbridge_join_cb(void *data, struct stasis_subscription *sub,
249         struct stasis_topic *topic,
250         struct stasis_message *message)
251 {
252         confbridge_publish_manager_event(message, "ConfbridgeJoin", NULL);
253 }
254
255 static void confbridge_start_record_cb(void *data, struct stasis_subscription *sub,
256         struct stasis_topic *topic,
257         struct stasis_message *message)
258 {
259         confbridge_publish_manager_event(message, "ConfbridgeRecord", NULL);
260 }
261
262 static void confbridge_stop_record_cb(void *data, struct stasis_subscription *sub,
263         struct stasis_topic *topic,
264         struct stasis_message *message)
265 {
266         confbridge_publish_manager_event(message, "ConfbridgeStopRecord", NULL);
267 }
268
269 static void confbridge_mute_cb(void *data, struct stasis_subscription *sub,
270         struct stasis_topic *topic,
271         struct stasis_message *message)
272 {
273         confbridge_publish_manager_event(message, "ConfbridgeMute", NULL);
274 }
275
276 static void confbridge_unmute_cb(void *data, struct stasis_subscription *sub,
277         struct stasis_topic *topic,
278         struct stasis_message *message)
279 {
280         confbridge_publish_manager_event(message, "ConfbridgeUnmute", NULL);
281 }
282
283 static void confbridge_talking_cb(void *data, struct stasis_subscription *sub,
284         struct stasis_topic *topic,
285         struct stasis_message *message)
286 {
287         RAII_VAR(struct ast_str *, extra_text, NULL, ast_free);
288         struct ast_bridge_blob *blob = stasis_message_data(message);
289         const char *talking_status = ast_json_string_get(ast_json_object_get(blob->blob, "talking_status"));
290         if (!talking_status) {
291                 return;
292         }
293
294         ast_str_append_event_header(&extra_text, "TalkingStatus", talking_status);
295         if (!extra_text) {
296                 return;
297         }
298
299         confbridge_publish_manager_event(message, "ConfbridgeTalking", extra_text);
300 }
301
302 STASIS_MESSAGE_TYPE_DEFN(confbridge_start_type);
303 STASIS_MESSAGE_TYPE_DEFN(confbridge_end_type);
304 STASIS_MESSAGE_TYPE_DEFN(confbridge_join_type);
305 STASIS_MESSAGE_TYPE_DEFN(confbridge_leave_type);
306 STASIS_MESSAGE_TYPE_DEFN(confbridge_start_record_type);
307 STASIS_MESSAGE_TYPE_DEFN(confbridge_stop_record_type);
308 STASIS_MESSAGE_TYPE_DEFN(confbridge_mute_type);
309 STASIS_MESSAGE_TYPE_DEFN(confbridge_unmute_type);
310 STASIS_MESSAGE_TYPE_DEFN(confbridge_talking_type);
311
312 void manager_confbridge_shutdown(void) {
313         STASIS_MESSAGE_TYPE_CLEANUP(confbridge_start_type);
314         STASIS_MESSAGE_TYPE_CLEANUP(confbridge_end_type);
315         STASIS_MESSAGE_TYPE_CLEANUP(confbridge_join_type);
316         STASIS_MESSAGE_TYPE_CLEANUP(confbridge_leave_type);
317         STASIS_MESSAGE_TYPE_CLEANUP(confbridge_start_record_type);
318         STASIS_MESSAGE_TYPE_CLEANUP(confbridge_stop_record_type);
319         STASIS_MESSAGE_TYPE_CLEANUP(confbridge_mute_type);
320         STASIS_MESSAGE_TYPE_CLEANUP(confbridge_unmute_type);
321         STASIS_MESSAGE_TYPE_CLEANUP(confbridge_talking_type);
322
323         if (bridge_state_router) {
324                 stasis_message_router_unsubscribe(bridge_state_router);
325                 bridge_state_router = NULL;
326         }
327
328         if (channel_state_router) {
329                 stasis_message_router_unsubscribe(channel_state_router);
330                 channel_state_router = NULL;
331         }
332 }
333
334 int manager_confbridge_init(void)
335 {
336         STASIS_MESSAGE_TYPE_INIT(confbridge_start_type);
337         STASIS_MESSAGE_TYPE_INIT(confbridge_end_type);
338         STASIS_MESSAGE_TYPE_INIT(confbridge_join_type);
339         STASIS_MESSAGE_TYPE_INIT(confbridge_leave_type);
340         STASIS_MESSAGE_TYPE_INIT(confbridge_start_record_type);
341         STASIS_MESSAGE_TYPE_INIT(confbridge_stop_record_type);
342         STASIS_MESSAGE_TYPE_INIT(confbridge_mute_type);
343         STASIS_MESSAGE_TYPE_INIT(confbridge_unmute_type);
344         STASIS_MESSAGE_TYPE_INIT(confbridge_talking_type);
345
346         bridge_state_router = stasis_message_router_create(
347                 stasis_caching_get_topic(ast_bridge_topic_all_cached()));
348
349         if (!bridge_state_router) {
350                 return -1;
351         }
352
353         if (stasis_message_router_add(bridge_state_router,
354                         confbridge_start_type(),
355                         confbridge_start_cb,
356                         NULL)) {
357                 manager_confbridge_shutdown();
358                 return -1;
359         }
360         if (stasis_message_router_add(bridge_state_router,
361                         confbridge_end_type(),
362                         confbridge_end_cb,
363                         NULL)) {
364                 manager_confbridge_shutdown();
365                 return -1;
366         }
367         if (stasis_message_router_add(bridge_state_router,
368                         confbridge_join_type(),
369                         confbridge_join_cb,
370                         NULL)) {
371                 manager_confbridge_shutdown();
372                 return -1;
373         }
374         if (stasis_message_router_add(bridge_state_router,
375                         confbridge_leave_type(),
376                         confbridge_leave_cb,
377                         NULL)) {
378                 manager_confbridge_shutdown();
379                 return -1;
380         }
381         if (stasis_message_router_add(bridge_state_router,
382                         confbridge_start_record_type(),
383                         confbridge_start_record_cb,
384                         NULL)) {
385                 manager_confbridge_shutdown();
386                 return -1;
387         }
388         if (stasis_message_router_add(bridge_state_router,
389                         confbridge_stop_record_type(),
390                         confbridge_stop_record_cb,
391                         NULL)) {
392                 manager_confbridge_shutdown();
393                 return -1;
394         }
395         if (stasis_message_router_add(bridge_state_router,
396                         confbridge_mute_type(),
397                         confbridge_mute_cb,
398                         NULL)) {
399                 manager_confbridge_shutdown();
400                 return -1;
401         }
402         if (stasis_message_router_add(bridge_state_router,
403                         confbridge_unmute_type(),
404                         confbridge_unmute_cb,
405                         NULL)) {
406                 manager_confbridge_shutdown();
407                 return -1;
408         }
409         if (stasis_message_router_add(bridge_state_router,
410                         confbridge_talking_type(),
411                         confbridge_talking_cb,
412                         NULL)) {
413                 manager_confbridge_shutdown();
414                 return -1;
415         }
416
417         channel_state_router = stasis_message_router_create(
418                 stasis_caching_get_topic(ast_channel_topic_all_cached()));
419
420         if (!channel_state_router) {
421                 manager_confbridge_shutdown();
422                 return -1;
423         }
424
425         if (stasis_message_router_add(channel_state_router,
426                         confbridge_start_type(),
427                         confbridge_start_cb,
428                         NULL)) {
429                 manager_confbridge_shutdown();
430                 return -1;
431         }
432         if (stasis_message_router_add(channel_state_router,
433                         confbridge_end_type(),
434                         confbridge_end_cb,
435                         NULL)) {
436                 manager_confbridge_shutdown();
437                 return -1;
438         }
439         if (stasis_message_router_add(channel_state_router,
440                         confbridge_join_type(),
441                         confbridge_join_cb,
442                         NULL)) {
443                 manager_confbridge_shutdown();
444                 return -1;
445         }
446         if (stasis_message_router_add(channel_state_router,
447                         confbridge_leave_type(),
448                         confbridge_leave_cb,
449                         NULL)) {
450                 manager_confbridge_shutdown();
451                 return -1;
452         }
453         if (stasis_message_router_add(channel_state_router,
454                         confbridge_start_record_type(),
455                         confbridge_start_record_cb,
456                         NULL)) {
457                 manager_confbridge_shutdown();
458                 return -1;
459         }
460         if (stasis_message_router_add(channel_state_router,
461                         confbridge_stop_record_type(),
462                         confbridge_stop_record_cb,
463                         NULL)) {
464                 manager_confbridge_shutdown();
465                 return -1;
466         }
467         if (stasis_message_router_add(channel_state_router,
468                         confbridge_mute_type(),
469                         confbridge_mute_cb,
470                         NULL)) {
471                 manager_confbridge_shutdown();
472                 return -1;
473         }
474         if (stasis_message_router_add(channel_state_router,
475                         confbridge_unmute_type(),
476                         confbridge_unmute_cb,
477                         NULL)) {
478                 manager_confbridge_shutdown();
479                 return -1;
480         }
481         if (stasis_message_router_add(channel_state_router,
482                         confbridge_talking_type(),
483                         confbridge_talking_cb,
484                         NULL)) {
485                 manager_confbridge_shutdown();
486                 return -1;
487         }
488
489         return 0;
490 }