Confbridge: Add "sfu" video mode to bridge profile options.
[asterisk/asterisk.git] / apps / app_confbridge.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2007-2008, Digium, Inc.
5  *
6  * Joshua Colp <jcolp@digium.com>
7  * David Vossel <dvossel@digium.com>
8  *
9  * See http://www.asterisk.org for more information about
10  * the Asterisk project. Please do not directly contact
11  * any of the maintainers of this project for assistance;
12  * the project provides a web site, mailing lists and IRC
13  * channels for your use.
14  *
15  * This program is free software, distributed under the terms of
16  * the GNU General Public License Version 2. See the LICENSE file
17  * at the top of the source tree.
18  */
19
20 /*! \file
21  *
22  * \brief Conference Bridge application
23  *
24  * \author\verbatim Joshua Colp <jcolp@digium.com> \endverbatim
25  * \author\verbatim David Vossel <dvossel@digium.com> \endverbatim
26  *
27  * This is a conference bridge application utilizing the bridging core.
28  * \ingroup applications
29  */
30
31 /*! \li \ref app_confbridge.c uses the configuration file \ref confbridge.conf
32  * \addtogroup configuration_file Configuration Files
33  */
34
35 /*!
36  * \page confbridge.conf confbridge.conf
37  * \verbinclude confbridge.conf.sample
38  */
39
40 /*** MODULEINFO
41         <support_level>core</support_level>
42  ***/
43
44 #include "asterisk.h"
45
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <unistd.h>
49 #include <string.h>
50 #include <signal.h>
51
52 #include "asterisk/cli.h"
53 #include "asterisk/file.h"
54 #include "asterisk/channel.h"
55 #include "asterisk/pbx.h"
56 #include "asterisk/pbx.h"
57 #include "asterisk/module.h"
58 #include "asterisk/lock.h"
59 #include "asterisk/bridge.h"
60 #include "asterisk/musiconhold.h"
61 #include "asterisk/say.h"
62 #include "asterisk/audiohook.h"
63 #include "asterisk/astobj2.h"
64 #include "confbridge/include/confbridge.h"
65 #include "asterisk/paths.h"
66 #include "asterisk/manager.h"
67 #include "asterisk/test.h"
68 #include "asterisk/stasis.h"
69 #include "asterisk/stasis_bridges.h"
70 #include "asterisk/json.h"
71 #include "asterisk/format_cache.h"
72 #include "asterisk/taskprocessor.h"
73
74 /*** DOCUMENTATION
75         <application name="ConfBridge" language="en_US">
76                 <synopsis>
77                         Conference bridge application.
78                 </synopsis>
79                 <syntax>
80                         <parameter name="conference" required="true">
81                                 <para>Name of the conference bridge.  You are not limited to just
82                                 numbers.</para>
83                         </parameter>
84                         <parameter name="bridge_profile">
85                                 <para>The bridge profile name from confbridge.conf.  When left blank,
86                                 a dynamically built bridge profile created by the CONFBRIDGE dialplan
87                                 function is searched for on the channel and used.  If no dynamic
88                                 profile is present, the 'default_bridge' profile found in
89                                 confbridge.conf is used. </para>
90                                 <para>It is important to note that while user profiles may be unique
91                                 for each participant, mixing bridge profiles on a single conference
92                                 is _NOT_ recommended and will produce undefined results.</para>
93                         </parameter>
94                         <parameter name="user_profile">
95                                 <para>The user profile name from confbridge.conf.  When left blank,
96                                 a dynamically built user profile created by the CONFBRIDGE dialplan
97                                 function is searched for on the channel and used.  If no dynamic
98                                 profile is present, the 'default_user' profile found in
99                                 confbridge.conf is used.</para>
100                         </parameter>
101                         <parameter name="menu">
102                                 <para>The name of the DTMF menu in confbridge.conf to be applied to
103                                 this channel.  When left blank, a dynamically built menu profile
104                                 created by the CONFBRIDGE dialplan function is searched for on
105                                 the channel and used. If no dynamic profile is present, the
106                                 'default_menu' profile found in confbridge.conf is used.</para>
107                         </parameter>
108                 </syntax>
109                 <description>
110                         <para>Enters the user into a specified conference bridge.  The user can
111                         exit the conference by hangup or DTMF menu option.</para>
112                         <para>This application sets the following channel variable upon completion:</para>
113                         <variablelist>
114                                 <variable name="CONFBRIDGE_RESULT">
115                                         <value name="FAILED">The channel encountered an error and could not enter the conference.</value>
116                                         <value name="HANGUP">The channel exited the conference by hanging up.</value>
117                                         <value name="KICKED">The channel was kicked from the conference.</value>
118                                         <value name="ENDMARKED">The channel left the conference as a result of the last marked user leaving.</value>
119                                         <value name="DTMF">The channel pressed a DTMF sequence to exit the conference.</value>
120                                         <value name="TIMEOUT">The channel reached its configured timeout.</value>
121                                 </variable>
122                         </variablelist>
123                 </description>
124                 <see-also>
125                         <ref type="application">ConfBridge</ref>
126                         <ref type="function">CONFBRIDGE</ref>
127                         <ref type="function">CONFBRIDGE_INFO</ref>
128                 </see-also>
129         </application>
130         <function name="CONFBRIDGE" language="en_US">
131                 <synopsis>
132                         Set a custom dynamic bridge, user, or menu profile on a channel for the
133                         ConfBridge application using the same options available in confbridge.conf.
134                 </synopsis>
135                 <syntax>
136                         <parameter name="type" required="true">
137                                 <para>To what type of conference profile the option applies.</para>
138                                 <enumlist>
139                                         <enum name="bridge"></enum>
140                                         <enum name="menu"></enum>
141                                         <enum name="user"></enum>
142                                 </enumlist>
143                         </parameter>
144                         <parameter name="option" required="true">
145                                 <para>Option refers to a <filename>confbridge.conf</filename> option
146                                 that is being set dynamically on this channel, or <literal>clear</literal>
147                                 to remove already applied profile options from the channel.</para>
148                         </parameter>
149                 </syntax>
150                 <description>
151                         <para>A custom profile uses the default profile type settings defined in
152                         <filename>confbridge.conf</filename> as defaults if the profile template
153                         is not explicitly specified first.</para>
154                         <para>For <literal>bridge</literal> profiles the default template is <literal>default_bridge</literal>.</para>
155                         <para>For <literal>menu</literal> profiles the default template is <literal>default_menu</literal>.</para>
156                         <para>For <literal>user</literal> profiles the default template is <literal>default_user</literal>.</para>
157                         <para>---- Example 1 ----</para>
158                         <para>In this example the custom user profile set on the channel will
159                         automatically be used by the ConfBridge application.</para>
160                         <para>exten => 1,1,Answer()</para>
161                         <para>; In this example the effect of the following line is</para>
162                         <para>; implied:</para>
163                         <para>; same => n,Set(CONFBRIDGE(user,template)=default_user)</para>
164                         <para>same => n,Set(CONFBRIDGE(user,announce_join_leave)=yes)</para>
165                         <para>same => n,Set(CONFBRIDGE(user,startmuted)=yes)</para>
166                         <para>same => n,ConfBridge(1) </para>
167                         <para>---- Example 2 ----</para>
168                         <para>This example shows how to use a predefined user profile in
169                         <filename>confbridge.conf</filename> as a template for a dynamic profile.
170                         Here we make an admin/marked user out of the <literal>my_user</literal>
171                         profile that you define in <filename>confbridge.conf</filename>.</para>
172                         <para>exten => 1,1,Answer()</para>
173                         <para>same => n,Set(CONFBRIDGE(user,template)=my_user)</para>
174                         <para>same => n,Set(CONFBRIDGE(user,admin)=yes)</para>
175                         <para>same => n,Set(CONFBRIDGE(user,marked)=yes)</para>
176                         <para>same => n,ConfBridge(1)</para>
177                 </description>
178         </function>
179         <function name="CONFBRIDGE_INFO" language="en_US">
180                 <synopsis>
181                         Get information about a ConfBridge conference.
182                 </synopsis>
183                 <syntax>
184                         <parameter name="type" required="true">
185                                 <para>What conference information is requested.</para>
186                                 <enumlist>
187                                         <enum name="admins">
188                                                 <para>Get the number of admin users in the conference.</para>
189                                         </enum>
190                                         <enum name="locked">
191                                                 <para>Determine if the conference is locked. (0 or 1)</para>
192                                         </enum>
193                                         <enum name="marked">
194                                                 <para>Get the number of marked users in the conference.</para>
195                                         </enum>
196                                         <enum name="muted">
197                                                 <para>Determine if the conference is muted. (0 or 1)</para>
198                                         </enum>
199                                         <enum name="parties">
200                                                 <para>Get the number of users in the conference.</para>
201                                         </enum>
202                                 </enumlist>
203                         </parameter>
204                         <parameter name="conf" required="true">
205                                 <para>The name of the conference being referenced.</para>
206                         </parameter>
207                 </syntax>
208                 <description>
209                         <para>This function returns a non-negative integer for valid conference
210                         names and an empty string for invalid conference names.</para>
211                 </description>
212         </function>
213         <manager name="ConfbridgeList" language="en_US">
214                 <synopsis>
215                         List participants in a conference.
216                 </synopsis>
217                 <syntax>
218                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
219                         <parameter name="Conference" required="true">
220                                 <para>Conference number.</para>
221                         </parameter>
222                 </syntax>
223                 <description>
224                         <para>Lists all users in a particular ConfBridge conference.
225                         ConfbridgeList will follow as separate events, followed by a final event called
226                         ConfbridgeListComplete.</para>
227                 </description>
228         </manager>
229         <manager name="ConfbridgeListRooms" language="en_US">
230                 <synopsis>
231                         List active conferences.
232                 </synopsis>
233                 <syntax>
234                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
235                 </syntax>
236                 <description>
237                         <para>Lists data about all active conferences.
238                                 ConfbridgeListRooms will follow as separate events, followed by a final event called
239                                 ConfbridgeListRoomsComplete.</para>
240                 </description>
241         </manager>
242         <manager name="ConfbridgeMute" language="en_US">
243                 <synopsis>
244                         Mute a Confbridge user.
245                 </synopsis>
246                 <syntax>
247                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
248                         <parameter name="Conference" required="true" />
249                         <parameter name="Channel" required="true">
250                                 <para>If this parameter is not a complete channel name, the first channel with this prefix will be used.</para>
251                                 <para>If this parameter is "all", all channels will be muted.</para>
252                                 <para>If this parameter is "participants", all non-admin channels will be muted.</para>
253                         </parameter>
254                 </syntax>
255                 <description>
256                 </description>
257         </manager>
258         <manager name="ConfbridgeUnmute" language="en_US">
259                 <synopsis>
260                         Unmute a Confbridge user.
261                 </synopsis>
262                 <syntax>
263                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
264                         <parameter name="Conference" required="true" />
265                         <parameter name="Channel" required="true">
266                                 <para>If this parameter is not a complete channel name, the first channel with this prefix will be used.</para>
267                                 <para>If this parameter is "all", all channels will be unmuted.</para>
268                                 <para>If this parameter is "participants", all non-admin channels will be unmuted.</para>
269                         </parameter>
270                 </syntax>
271                 <description>
272                 </description>
273         </manager>
274         <manager name="ConfbridgeKick" language="en_US">
275                 <synopsis>
276                         Kick a Confbridge user.
277                 </synopsis>
278                 <syntax>
279                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
280                         <parameter name="Conference" required="true" />
281                         <parameter name="Channel" required="true" >
282                                 <para>If this parameter is "all", all channels will be kicked from the conference.</para>
283                                 <para>If this parameter is "participants", all non-admin channels will be kicked from the conference.</para>
284                         </parameter>
285                 </syntax>
286                 <description>
287                 </description>
288         </manager>
289         <manager name="ConfbridgeLock" language="en_US">
290                 <synopsis>
291                         Lock a Confbridge conference.
292                 </synopsis>
293                 <syntax>
294                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
295                         <parameter name="Conference" required="true" />
296                 </syntax>
297                 <description>
298                 </description>
299         </manager>
300         <manager name="ConfbridgeUnlock" language="en_US">
301                 <synopsis>
302                         Unlock a Confbridge conference.
303                 </synopsis>
304                 <syntax>
305                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
306                         <parameter name="Conference" required="true" />
307                 </syntax>
308                 <description>
309                 </description>
310         </manager>
311         <manager name="ConfbridgeStartRecord" language="en_US">
312                 <synopsis>
313                         Start recording a Confbridge conference.
314                 </synopsis>
315                 <syntax>
316                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
317                         <parameter name="Conference" required="true" />
318                         <parameter name="RecordFile" required="false" />
319                 </syntax>
320                 <description>
321                         <para>Start recording a conference. If recording is already present an error will be returned. If RecordFile is not provided, the default record file specified in the conference's bridge profile will be used, if that is not present either a file will automatically be generated in the monitor directory.</para>
322                 </description>
323         </manager>
324         <manager name="ConfbridgeStopRecord" language="en_US">
325                 <synopsis>
326                         Stop recording a Confbridge conference.
327                 </synopsis>
328                 <syntax>
329                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
330                         <parameter name="Conference" required="true" />
331                 </syntax>
332                 <description>
333                 </description>
334         </manager>
335         <manager name="ConfbridgeSetSingleVideoSrc" language="en_US">
336                 <synopsis>
337                         Set a conference user as the single video source distributed to all other participants.
338                 </synopsis>
339                 <syntax>
340                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
341                         <parameter name="Conference" required="true" />
342                         <parameter name="Channel" required="true">
343                                 <para>If this parameter is not a complete channel name, the first channel with this prefix will be used.</para>
344                         </parameter>
345                 </syntax>
346                 <description>
347                 </description>
348         </manager>
349
350 ***/
351
352 /*!
353  * \par Playing back a file to a channel in a conference
354  * You might notice in this application that while playing a sound file
355  * to a channel the actual conference bridge lock is not held. This is done so
356  * that other channels are not blocked from interacting with the conference bridge.
357  * Unfortunately because of this it is possible for things to change after the sound file
358  * is done being played. Data must therefore be checked after reacquiring the conference
359  * bridge lock if it is important.
360  */
361
362 static const char app[] = "ConfBridge";
363
364 /*! Number of buckets our conference bridges container can have */
365 #define CONFERENCE_BRIDGE_BUCKETS 53
366
367 /*! Initial recording filename space. */
368 #define RECORD_FILENAME_INITIAL_SPACE   128
369
370 /*! \brief Container to hold all conference bridges in progress */
371 struct ao2_container *conference_bridges;
372
373 static void leave_conference(struct confbridge_user *user);
374 static int play_sound_number(struct confbridge_conference *conference, int say_number);
375 static int execute_menu_entry(struct confbridge_conference *conference,
376         struct confbridge_user *user,
377         struct ast_bridge_channel *bridge_channel,
378         struct conf_menu_entry *menu_entry,
379         struct conf_menu *menu);
380
381 /*! \brief Hashing function used for conference bridges container */
382 static int conference_bridge_hash_cb(const void *obj, const int flags)
383 {
384         const struct confbridge_conference *conference = obj;
385         const char *name = obj;
386         int hash;
387
388         switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
389         default:
390         case OBJ_POINTER:
391                 name = conference->name;
392                 /* Fall through */
393         case OBJ_KEY:
394                 hash = ast_str_case_hash(name);
395                 break;
396         case OBJ_PARTIAL_KEY:
397                 /* Should never happen in hash callback. */
398                 ast_assert(0);
399                 hash = 0;
400                 break;
401         }
402         return hash;
403 }
404
405 /*! \brief Comparison function used for conference bridges container */
406 static int conference_bridge_cmp_cb(void *obj, void *arg, int flags)
407 {
408         const struct confbridge_conference *left = obj;
409         const struct confbridge_conference *right = arg;
410         const char *right_name = arg;
411         int cmp;
412
413         switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
414         default:
415         case OBJ_POINTER:
416                 right_name = right->name;
417                 /* Fall through */
418         case OBJ_KEY:
419                 cmp = strcasecmp(left->name, right_name);
420                 break;
421         case OBJ_PARTIAL_KEY:
422                 cmp = strncasecmp(left->name, right_name, strlen(right_name));
423                 break;
424         }
425         return cmp ? 0 : CMP_MATCH;
426 }
427
428 const char *conf_get_sound(enum conf_sounds sound, struct bridge_profile_sounds *custom_sounds)
429 {
430         switch (sound) {
431         case CONF_SOUND_HAS_JOINED:
432                 return S_OR(custom_sounds->hasjoin, "conf-hasjoin");
433         case CONF_SOUND_HAS_LEFT:
434                 return S_OR(custom_sounds->hasleft, "conf-hasleft");
435         case CONF_SOUND_KICKED:
436                 return S_OR(custom_sounds->kicked, "conf-kicked");
437         case CONF_SOUND_MUTED:
438                 return S_OR(custom_sounds->muted, "conf-muted");
439         case CONF_SOUND_UNMUTED:
440                 return S_OR(custom_sounds->unmuted, "conf-unmuted");
441         case CONF_SOUND_BINAURAL_ON:
442                 return S_OR(custom_sounds->binauralon, "confbridge-binaural-on");
443         case CONF_SOUND_BINAURAL_OFF:
444                 return S_OR(custom_sounds->binauraloff, "confbridge-binaural-off");
445         case CONF_SOUND_ONLY_ONE:
446                 return S_OR(custom_sounds->onlyone, "conf-onlyone");
447         case CONF_SOUND_THERE_ARE:
448                 return S_OR(custom_sounds->thereare, "conf-thereare");
449         case CONF_SOUND_OTHER_IN_PARTY:
450                 return S_OR(custom_sounds->otherinparty, "conf-otherinparty");
451         case CONF_SOUND_PLACE_IN_CONF:
452                 return S_OR(custom_sounds->placeintoconf, "conf-placeintoconf");
453         case CONF_SOUND_WAIT_FOR_LEADER:
454                 return S_OR(custom_sounds->waitforleader, "conf-waitforleader");
455         case CONF_SOUND_LEADER_HAS_LEFT:
456                 return S_OR(custom_sounds->leaderhasleft, "conf-leaderhasleft");
457         case CONF_SOUND_GET_PIN:
458                 return S_OR(custom_sounds->getpin, "conf-getpin");
459         case CONF_SOUND_INVALID_PIN:
460                 return S_OR(custom_sounds->invalidpin, "conf-invalidpin");
461         case CONF_SOUND_ONLY_PERSON:
462                 return S_OR(custom_sounds->onlyperson, "conf-onlyperson");
463         case CONF_SOUND_LOCKED:
464                 return S_OR(custom_sounds->locked, "conf-locked");
465         case CONF_SOUND_LOCKED_NOW:
466                 return S_OR(custom_sounds->lockednow, "conf-lockednow");
467         case CONF_SOUND_UNLOCKED_NOW:
468                 return S_OR(custom_sounds->unlockednow, "conf-unlockednow");
469         case CONF_SOUND_ERROR_MENU:
470                 return S_OR(custom_sounds->errormenu, "conf-errormenu");
471         case CONF_SOUND_JOIN:
472                 return S_OR(custom_sounds->join, "confbridge-join");
473         case CONF_SOUND_LEAVE:
474                 return S_OR(custom_sounds->leave, "confbridge-leave");
475         case CONF_SOUND_PARTICIPANTS_MUTED:
476                 return S_OR(custom_sounds->participantsmuted, "conf-now-muted");
477         case CONF_SOUND_PARTICIPANTS_UNMUTED:
478                 return S_OR(custom_sounds->participantsunmuted, "conf-now-unmuted");
479         case CONF_SOUND_BEGIN:
480                 return S_OR(custom_sounds->begin, "confbridge-conf-begin");
481         }
482
483         return "";
484 }
485
486 static void send_conf_stasis(struct confbridge_conference *conference, struct ast_channel *chan,
487         struct stasis_message_type *type, struct ast_json *extras, int channel_topic)
488 {
489         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
490         RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
491
492         json_object = ast_json_pack("{s: s}",
493                 "conference", conference->name);
494         if (!json_object) {
495                 return;
496         }
497
498         if (extras) {
499                 ast_json_object_update(json_object, extras);
500         }
501
502         ast_bridge_lock(conference->bridge);
503         msg = ast_bridge_blob_create(type,
504                 conference->bridge,
505                 chan,
506                 json_object);
507         ast_bridge_unlock(conference->bridge);
508         if (!msg) {
509                 return;
510         }
511
512         if (channel_topic) {
513                 stasis_publish(ast_channel_topic(chan), msg);
514         } else {
515                 stasis_publish(ast_bridge_topic(conference->bridge), msg);
516         }
517 }
518
519 static void send_conf_start_event(struct confbridge_conference *conference)
520 {
521         send_conf_stasis(conference, NULL, confbridge_start_type(), NULL, 0);
522 }
523
524 static void send_conf_end_event(struct confbridge_conference *conference)
525 {
526         send_conf_stasis(conference, NULL, confbridge_end_type(), NULL, 0);
527 }
528
529 static void send_join_event(struct confbridge_user *user, struct confbridge_conference *conference)
530 {
531         struct ast_json *json_object;
532
533         json_object = ast_json_pack("{s: b}",
534                 "admin", ast_test_flag(&user->u_profile, USER_OPT_ADMIN)
535         );
536         if (!json_object) {
537                 return;
538         }
539         send_conf_stasis(conference, user->chan, confbridge_join_type(), json_object, 0);
540         ast_json_unref(json_object);
541 }
542
543 static void send_leave_event(struct confbridge_user *user, struct confbridge_conference *conference)
544 {
545         struct ast_json *json_object;
546
547         json_object = ast_json_pack("{s: b}",
548                 "admin", ast_test_flag(&user->u_profile, USER_OPT_ADMIN)
549         );
550         if (!json_object) {
551                 return;
552         }
553         send_conf_stasis(conference, user->chan, confbridge_leave_type(), json_object, 0);
554         ast_json_unref(json_object);
555 }
556
557 static void send_start_record_event(struct confbridge_conference *conference)
558 {
559         send_conf_stasis(conference, NULL, confbridge_start_record_type(), NULL, 0);
560 }
561
562 static void send_stop_record_event(struct confbridge_conference *conference)
563 {
564         send_conf_stasis(conference, NULL, confbridge_stop_record_type(), NULL, 0);
565 }
566
567 static void send_mute_event(struct confbridge_user *user, struct confbridge_conference *conference)
568 {
569         struct ast_json *json_object;
570
571         json_object = ast_json_pack("{s: b}",
572                 "admin", ast_test_flag(&user->u_profile, USER_OPT_ADMIN)
573         );
574         if (!json_object) {
575                 return;
576         }
577         send_conf_stasis(conference, user->chan, confbridge_mute_type(), json_object, 1);
578         ast_json_unref(json_object);
579 }
580
581 static void send_unmute_event(struct confbridge_user *user, struct confbridge_conference *conference)
582 {
583         struct ast_json *json_object;
584
585         json_object = ast_json_pack("{s: b}",
586                 "admin", ast_test_flag(&user->u_profile, USER_OPT_ADMIN)
587         );
588         if (!json_object) {
589                 return;
590         }
591         send_conf_stasis(conference, user->chan, confbridge_unmute_type(), json_object, 1);
592         ast_json_unref(json_object);
593 }
594
595 static void set_rec_filename(struct confbridge_conference *conference, struct ast_str **filename, int is_new)
596 {
597         char *rec_file = conference->b_profile.rec_file;
598         char *ext;
599         time_t now;
600
601         if (ast_str_strlen(*filename)
602                 && ast_test_flag(&conference->b_profile, BRIDGE_OPT_RECORD_FILE_APPEND)
603                 && !is_new) {
604                 return;
605         }
606
607         time(&now);
608
609         ast_str_reset(*filename);
610         if (ast_strlen_zero(rec_file)) {
611                 ast_str_set(filename, 0, "confbridge-%s-%u.wav", conference->name,
612                         (unsigned int) now);
613         } else if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_RECORD_FILE_TIMESTAMP)) {
614                 /* insert time before file extension */
615                 ext = strrchr(rec_file, '.');
616                 if (ext) {
617                         ast_str_set_substr(filename, 0, rec_file, ext - rec_file);
618                         ast_str_append(filename, 0, "-%u%s", (unsigned int) now, ext);
619                 } else {
620                         ast_str_set(filename, 0, "%s-%u", rec_file, (unsigned int) now);
621                 }
622         } else {
623                 ast_str_set(filename, 0, "%s", rec_file);
624         }
625         ast_str_append(filename, 0, ",%s%s,%s",
626                 ast_test_flag(&conference->b_profile, BRIDGE_OPT_RECORD_FILE_APPEND) ? "a" : "",
627                 conference->b_profile.rec_options,
628                 conference->b_profile.rec_command);
629 }
630
631 static int is_new_rec_file(const char *rec_file, struct ast_str **orig_rec_file)
632 {
633         if (!ast_strlen_zero(rec_file)) {
634                 if (!*orig_rec_file) {
635                         *orig_rec_file = ast_str_create(RECORD_FILENAME_INITIAL_SPACE);
636                 }
637
638                 if (*orig_rec_file
639                         && strcmp(ast_str_buffer(*orig_rec_file), rec_file)) {
640                         ast_str_set(orig_rec_file, 0, "%s", rec_file);
641                         return 1;
642                 }
643         }
644         return 0;
645 }
646
647 /*!
648  * \internal
649  * \brief Returns whether or not conference is being recorded.
650  *
651  * \param conference The bridge to check for recording
652  *
653  * \note Must be called with the conference locked
654  *
655  * \retval 1, conference is recording.
656  * \retval 0, conference is NOT recording.
657  */
658 static int conf_is_recording(struct confbridge_conference *conference)
659 {
660         return conference->record_chan != NULL;
661 }
662
663 /*!
664  * \internal
665  * \brief Stop recording a conference bridge
666  *
667  * \param conference The conference bridge on which to stop the recording
668  *
669  * \note Must be called with the conference locked
670  *
671  * \retval -1 Failure
672  * \retval 0 Success
673  */
674 static int conf_stop_record(struct confbridge_conference *conference)
675 {
676         struct ast_channel *chan;
677         struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_HANGUP };
678
679         if (!conf_is_recording(conference)) {
680                 return -1;
681         }
682
683         /* Remove the recording channel from the conference bridge. */
684         chan = conference->record_chan;
685         conference->record_chan = NULL;
686         ast_queue_frame(chan, &f);
687         ast_channel_unref(chan);
688
689         ast_test_suite_event_notify("CONF_STOP_RECORD", "Message: stopped conference recording channel\r\nConference: %s", conference->b_profile.name);
690         send_stop_record_event(conference);
691
692         return 0;
693 }
694
695 /*!
696  * \internal
697  * \brief Start recording the conference
698  *
699  * \param conference The conference bridge to start recording
700  *
701  * \note Must be called with the conference locked
702  *
703  * \retval 0 success
704  * \retval non-zero failure
705  */
706 static int conf_start_record(struct confbridge_conference *conference)
707 {
708         struct ast_app *mixmonapp;
709         struct ast_channel *chan;
710         struct ast_format_cap *cap;
711         struct ast_bridge_features *features;
712
713         if (conf_is_recording(conference)) {
714                 return -1;
715         }
716
717         mixmonapp = pbx_findapp("MixMonitor");
718         if (!mixmonapp) {
719                 ast_log(LOG_WARNING, "Cannot record ConfBridge, MixMonitor app is not installed\n");
720                 return -1;
721         }
722
723         features = ast_bridge_features_new();
724         if (!features) {
725                 return -1;
726         }
727         ast_set_flag(&features->feature_flags, AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE);
728
729         cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
730         if (!cap) {
731                 ast_bridge_features_destroy(features);
732                 return -1;
733         }
734         ast_format_cap_append(cap, ast_format_slin, 0);
735
736         /* Create the recording channel. */
737         chan = ast_request("CBRec", cap, NULL, NULL, conference->name, NULL);
738         ao2_ref(cap, -1);
739         if (!chan) {
740                 ast_bridge_features_destroy(features);
741                 return -1;
742         }
743
744         /* Start recording. */
745         set_rec_filename(conference, &conference->record_filename,
746                 is_new_rec_file(conference->b_profile.rec_file, &conference->orig_rec_file));
747         ast_answer(chan);
748         pbx_exec(chan, mixmonapp, ast_str_buffer(conference->record_filename));
749
750         /* Put the channel into the conference bridge. */
751         ast_channel_ref(chan);
752         conference->record_chan = chan;
753         if (ast_bridge_impart(conference->bridge, chan, NULL, features,
754                 AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) {
755                 ast_hangup(chan);
756                 ast_channel_unref(chan);
757                 conference->record_chan = NULL;
758                 return -1;
759         }
760
761         ast_test_suite_event_notify("CONF_START_RECORD", "Message: started conference recording channel\r\nConference: %s", conference->b_profile.name);
762         send_start_record_event(conference);
763
764         return 0;
765 }
766
767 /* \brief Playback the given filename and monitor for any dtmf interrupts.
768  *
769  * This function is used to playback sound files on a given channel and optionally
770  * allow dtmf interrupts to occur.
771  *
772  * If the optional bridge_channel parameter is given then sound file playback
773  * is played on that channel and dtmf interruptions are allowed. However, if
774  * bridge_channel is not set then the channel parameter is expected to be set
775  * instead and non interruptible playback is played on that channel.
776  *
777  * \param bridge_channel Bridge channel to play file on
778  * \param channel Optional channel to play file on if bridge_channel not given
779  * \param filename The file name to playback
780  *
781  * \retval -1 failure during playback, 0 on file was fully played, 1 on dtmf interrupt.
782  */
783 static int play_file(struct ast_bridge_channel *bridge_channel, struct ast_channel *channel,
784                      const char *filename)
785 {
786         struct ast_channel *chan;
787         const char *stop_digits;
788         int digit;
789
790         if (bridge_channel) {
791                 chan = bridge_channel->chan;
792                 stop_digits = AST_DIGIT_ANY;
793         } else {
794                 chan = channel;
795                 stop_digits = AST_DIGIT_NONE;
796         }
797
798         digit = ast_stream_and_wait(chan, filename, stop_digits);
799         if (digit < 0) {
800                 ast_log(LOG_WARNING, "Failed to playback file '%s' to channel\n", filename);
801                 return -1;
802         }
803
804         if (digit > 0) {
805                 ast_stopstream(bridge_channel->chan);
806                 ast_bridge_channel_feature_digit_add(bridge_channel, digit);
807                 return 1;
808         }
809
810         return 0;
811 }
812
813 /*!
814  * \internal
815  * \brief Complain if the given sound file does not exist.
816  *
817  * \param filename Sound file to check if exists.
818  *
819  * \retval non-zero if the file exists.
820  */
821 static int sound_file_exists(const char *filename)
822 {
823         if (ast_fileexists(filename, NULL, NULL)) {
824                 return -1;
825         }
826         ast_log(LOG_WARNING, "File %s does not exist in any format\n", filename);
827         return 0;
828 }
829
830 /*!
831  * \brief Announce number of users in the conference bridge to the caller
832  *
833  * \param conference Conference bridge to peek at
834  * \param user Optional Caller
835  * \param bridge_channel The bridged channel involved
836  *
837  * \note if caller is NULL, the announcment will be sent to all participants in the conference.
838  * \return Returns 0 on success, -1 if the user hung up
839  */
840 static int announce_user_count(struct confbridge_conference *conference, struct confbridge_user *user,
841                                struct ast_bridge_channel *bridge_channel)
842 {
843         const char *other_in_party = conf_get_sound(CONF_SOUND_OTHER_IN_PARTY, conference->b_profile.sounds);
844         const char *only_one = conf_get_sound(CONF_SOUND_ONLY_ONE, conference->b_profile.sounds);
845         const char *there_are = conf_get_sound(CONF_SOUND_THERE_ARE, conference->b_profile.sounds);
846
847         if (conference->activeusers <= 1) {
848                 /* Awww we are the only person in the conference bridge OR we only have waitmarked users */
849                 return 0;
850         } else if (conference->activeusers == 2) {
851                 if (user) {
852                         /* Eep, there is one other person */
853                         if (play_file(bridge_channel, user->chan, only_one) < 0) {
854                                 return -1;
855                         }
856                 } else {
857                         play_sound_file(conference, only_one);
858                 }
859         } else {
860                 /* Alas multiple others in here */
861                 if (user) {
862                         if (ast_stream_and_wait(user->chan,
863                                 there_are,
864                                 "")) {
865                                 return -1;
866                         }
867                         if (ast_say_number(user->chan, conference->activeusers - 1, "", ast_channel_language(user->chan), NULL)) {
868                                 return -1;
869                         }
870                         if (play_file(bridge_channel, user->chan, other_in_party) < 0) {
871                                 return -1;
872                         }
873                 } else if (sound_file_exists(there_are) && sound_file_exists(other_in_party)) {
874                         play_sound_file(conference, there_are);
875                         play_sound_number(conference, conference->activeusers - 1);
876                         play_sound_file(conference, other_in_party);
877                 }
878         }
879         return 0;
880 }
881
882 /*!
883  * \brief Play back an audio file to a channel
884  *
885  * \param user User to play audio prompt to
886  * \param filename Prompt to play
887  *
888  * \return Returns 0 on success, -1 if the user hung up
889  * \note Generally this should be called when the conference is unlocked to avoid blocking
890  * the entire conference while the sound is played. But don't unlock the conference bridge
891  * in the middle of a state transition.
892  */
893 static int play_prompt_to_user(struct confbridge_user *user, const char *filename)
894 {
895         return ast_stream_and_wait(user->chan, filename, "");
896 }
897
898 static void handle_video_on_join(struct confbridge_conference *conference, struct ast_channel *chan, int marked)
899 {
900         /* Right now, only marked users are automatically set as the single src of video.*/
901         if (!marked) {
902                 return;
903         }
904
905         if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED)) {
906                 int set = 1;
907                 struct confbridge_user *user = NULL;
908
909                 ao2_lock(conference);
910                 /* see if anyone is already the video src */
911                 AST_LIST_TRAVERSE(&conference->active_list, user, list) {
912                         if (user->chan == chan) {
913                                 continue;
914                         }
915                         if (ast_bridge_is_video_src(conference->bridge, user->chan)) {
916                                 set = 0;
917                                 break;
918                         }
919                 }
920                 ao2_unlock(conference);
921                 if (set) {
922                         ast_bridge_set_single_src_video_mode(conference->bridge, chan);
923                 }
924         } else if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_VIDEO_SRC_LAST_MARKED)) {
925                 /* we joined and are video capable, we override anyone else that may have already been the video feed */
926                 ast_bridge_set_single_src_video_mode(conference->bridge, chan);
927         }
928 }
929
930 static void handle_video_on_exit(struct confbridge_conference *conference, struct ast_channel *chan)
931 {
932         struct confbridge_user *user = NULL;
933
934         /* if this isn't a video source, nothing to update */
935         if (!ast_bridge_is_video_src(conference->bridge, chan)) {
936                 return;
937         }
938
939         ast_bridge_remove_video_src(conference->bridge, chan);
940
941         /* If in follow talker mode, make sure to restore this mode on the
942          * bridge when a source is removed.  It is possible this channel was
943          * only set temporarily as a video source by an AMI or DTMF action. */
944         if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER)) {
945                 ast_bridge_set_talker_src_video_mode(conference->bridge);
946         }
947
948         /* if the video_mode isn't set to automatically pick the video source, do nothing on exit. */
949         if (!ast_test_flag(&conference->b_profile, BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED) &&
950                 !ast_test_flag(&conference->b_profile, BRIDGE_OPT_VIDEO_SRC_LAST_MARKED)) {
951                 return;
952         }
953
954         /* Make the next available marked user the video src.  */
955         ao2_lock(conference);
956         AST_LIST_TRAVERSE(&conference->active_list, user, list) {
957                 if (user->chan == chan) {
958                         continue;
959                 }
960                 if (ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER)) {
961                         ast_bridge_set_single_src_video_mode(conference->bridge, user->chan);
962                         break;
963                 }
964         }
965         ao2_unlock(conference);
966 }
967
968 struct hangup_data
969 {
970         struct confbridge_conference *conference;
971         ast_mutex_t lock;
972         ast_cond_t cond;
973         int hungup;
974 };
975
976 /*!
977  * \brief Hang up the announcer channel
978  *
979  * This hangs up the announcer channel in the conference. This
980  * runs in the playback queue taskprocessor since we do not want
981  * to hang up the channel while it's trying to play an announcement.
982  *
983  * This task is performed synchronously, so there is no need to
984  * perform any cleanup on the passed-in data.
985  *
986  * \param data A hangup_data structure
987  * \return 0
988  */
989 static int hangup_playback(void *data)
990 {
991         struct hangup_data *hangup = data;
992
993         ast_autoservice_stop(hangup->conference->playback_chan);
994
995         ast_hangup(hangup->conference->playback_chan);
996         hangup->conference->playback_chan = NULL;
997
998         ast_mutex_lock(&hangup->lock);
999         hangup->hungup = 1;
1000         ast_cond_signal(&hangup->cond);
1001         ast_mutex_unlock(&hangup->lock);
1002
1003         return 0;
1004 }
1005
1006 static void hangup_data_init(struct hangup_data *hangup, struct confbridge_conference *conference)
1007 {
1008         ast_mutex_init(&hangup->lock);
1009         ast_cond_init(&hangup->cond, NULL);
1010
1011         hangup->conference = conference;
1012         hangup->hungup = 0;
1013 }
1014
1015 static void hangup_data_destroy(struct hangup_data *hangup)
1016 {
1017         ast_mutex_destroy(&hangup->lock);
1018         ast_cond_destroy(&hangup->cond);
1019 }
1020
1021 /*!
1022  * \brief Destroy a conference bridge
1023  *
1024  * \param obj The conference bridge object
1025  *
1026  * \return Returns nothing
1027  */
1028 static void destroy_conference_bridge(void *obj)
1029 {
1030         struct confbridge_conference *conference = obj;
1031
1032         ast_debug(1, "Destroying conference bridge '%s'\n", conference->name);
1033
1034         if (conference->playback_chan) {
1035                 if (conference->playback_queue) {
1036                         struct hangup_data hangup;
1037                         hangup_data_init(&hangup, conference);
1038                         ast_taskprocessor_push(conference->playback_queue, hangup_playback, &hangup);
1039
1040                         ast_mutex_lock(&hangup.lock);
1041                         while (!hangup.hungup) {
1042                                 ast_cond_wait(&hangup.cond, &hangup.lock);
1043                         }
1044                         ast_mutex_unlock(&hangup.lock);
1045                         hangup_data_destroy(&hangup);
1046                 } else {
1047                         /* Playback queue is not yet allocated. Just hang up the channel straight */
1048                         ast_hangup(conference->playback_chan);
1049                         conference->playback_chan = NULL;
1050                 }
1051         }
1052
1053         /* Destroying a conference bridge is simple, all we have to do is destroy the bridging object */
1054         if (conference->bridge) {
1055                 ast_bridge_destroy(conference->bridge, 0);
1056                 conference->bridge = NULL;
1057         }
1058
1059         ast_channel_cleanup(conference->record_chan);
1060         ast_free(conference->orig_rec_file);
1061         ast_free(conference->record_filename);
1062
1063         conf_bridge_profile_destroy(&conference->b_profile);
1064         ast_taskprocessor_unreference(conference->playback_queue);
1065 }
1066
1067 /*! \brief Call the proper join event handler for the user for the conference bridge's current state
1068  * \internal
1069  * \param user The conference bridge user that is joining
1070  * \retval 0 success
1071  * \retval -1 failure
1072  */
1073 static int handle_conf_user_join(struct confbridge_user *user)
1074 {
1075         conference_event_fn handler;
1076         if (ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER)) {
1077                 handler = user->conference->state->join_marked;
1078         } else if (ast_test_flag(&user->u_profile, USER_OPT_WAITMARKED)) {
1079                 handler = user->conference->state->join_waitmarked;
1080         } else {
1081                 handler = user->conference->state->join_unmarked;
1082         }
1083
1084         ast_assert(handler != NULL);
1085
1086         if (!handler) {
1087                 conf_invalid_event_fn(user);
1088                 return -1;
1089         }
1090
1091         handler(user);
1092
1093         return 0;
1094 }
1095
1096 /*! \brief Call the proper leave event handler for the user for the conference bridge's current state
1097  * \internal
1098  * \param user The conference bridge user that is leaving
1099  * \retval 0 success
1100  * \retval -1 failure
1101  */
1102 static int handle_conf_user_leave(struct confbridge_user *user)
1103 {
1104         conference_event_fn handler;
1105         if (ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER)) {
1106                 handler = user->conference->state->leave_marked;
1107         } else if (ast_test_flag(&user->u_profile, USER_OPT_WAITMARKED)) {
1108                 handler = user->conference->state->leave_waitmarked;
1109         } else {
1110                 handler = user->conference->state->leave_unmarked;
1111         }
1112
1113         ast_assert(handler != NULL);
1114
1115         if (!handler) {
1116                 /* This should never happen. If it does, though, it is bad. The user will not have been removed
1117                  * from the appropriate list, so counts will be off and stuff. The conference won't be torn down, etc.
1118                  * Shouldn't happen, though. */
1119                 conf_invalid_event_fn(user);
1120                 return -1;
1121         }
1122
1123         handler(user);
1124
1125         return 0;
1126 }
1127
1128 void conf_update_user_mute(struct confbridge_user *user)
1129 {
1130         int mute_user;
1131         int mute_system;
1132         int mute_effective;
1133
1134         /* User level mute request. */
1135         mute_user = user->muted;
1136
1137         /* System level mute request. */
1138         mute_system = user->playing_moh
1139                 /*
1140                  * Do not allow waitmarked users to talk to anyone unless there
1141                  * is a marked user present.
1142                  */
1143                 || (!user->conference->markedusers
1144                         && ast_test_flag(&user->u_profile, USER_OPT_WAITMARKED));
1145
1146         mute_effective = mute_user || mute_system;
1147
1148         ast_debug(1, "User %s is %s: user:%d system:%d.\n",
1149                 ast_channel_name(user->chan), mute_effective ? "muted" : "unmuted",
1150                 mute_user, mute_system);
1151         user->features.mute = mute_effective;
1152         ast_test_suite_event_notify("CONF_MUTE_UPDATE",
1153                 "Mode: %s\r\n"
1154                 "Conference: %s\r\n"
1155                 "Channel: %s",
1156                 mute_effective ? "muted" : "unmuted",
1157                 user->conference->b_profile.name,
1158                 ast_channel_name(user->chan));
1159 }
1160
1161 /*
1162  * \internal
1163  * \brief Mute/unmute a single user.
1164  */
1165 static void generic_mute_unmute_user(struct confbridge_conference *conference, struct confbridge_user *user, int mute)
1166 {
1167         /* Set user level mute request. */
1168         user->muted = mute ? 1 : 0;
1169
1170         conf_update_user_mute(user);
1171         ast_test_suite_event_notify("CONF_MUTE",
1172                 "Message: participant %s %s\r\n"
1173                 "Conference: %s\r\n"
1174                 "Channel: %s",
1175                 ast_channel_name(user->chan),
1176                 mute ? "muted" : "unmuted",
1177                 conference->b_profile.name,
1178                 ast_channel_name(user->chan));
1179         if (mute) {
1180                 send_mute_event(user, conference);
1181         } else {
1182                 send_unmute_event(user, conference);
1183         }
1184 }
1185
1186 void conf_moh_stop(struct confbridge_user *user)
1187 {
1188         user->playing_moh = 0;
1189         if (!user->suspended_moh) {
1190                 int in_bridge;
1191
1192                 /*
1193                  * Locking the ast_bridge here is the only way to hold off the
1194                  * call to ast_bridge_join() in confbridge_exec() from
1195                  * interfering with the bridge and MOH operations here.
1196                  */
1197                 ast_bridge_lock(user->conference->bridge);
1198
1199                 /*
1200                  * Temporarily suspend the user from the bridge so we have
1201                  * control to stop MOH if needed.
1202                  */
1203                 in_bridge = !ast_bridge_suspend(user->conference->bridge, user->chan);
1204                 ast_moh_stop(user->chan);
1205                 if (in_bridge) {
1206                         ast_bridge_unsuspend(user->conference->bridge, user->chan);
1207                 }
1208
1209                 ast_bridge_unlock(user->conference->bridge);
1210         }
1211 }
1212
1213 void conf_moh_start(struct confbridge_user *user)
1214 {
1215         user->playing_moh = 1;
1216         if (!user->suspended_moh) {
1217                 int in_bridge;
1218
1219                 /*
1220                  * Locking the ast_bridge here is the only way to hold off the
1221                  * call to ast_bridge_join() in confbridge_exec() from
1222                  * interfering with the bridge and MOH operations here.
1223                  */
1224                 ast_bridge_lock(user->conference->bridge);
1225
1226                 /*
1227                  * Temporarily suspend the user from the bridge so we have
1228                  * control to start MOH if needed.
1229                  */
1230                 in_bridge = !ast_bridge_suspend(user->conference->bridge, user->chan);
1231                 ast_moh_start(user->chan, user->u_profile.moh_class, NULL);
1232                 if (in_bridge) {
1233                         ast_bridge_unsuspend(user->conference->bridge, user->chan);
1234                 }
1235
1236                 ast_bridge_unlock(user->conference->bridge);
1237         }
1238 }
1239
1240 /*!
1241  * \internal
1242  * \brief Unsuspend MOH for the conference user.
1243  *
1244  * \param user Conference user to unsuspend MOH on.
1245  *
1246  * \return Nothing
1247  */
1248 static void conf_moh_unsuspend(struct confbridge_user *user)
1249 {
1250         ao2_lock(user->conference);
1251         if (--user->suspended_moh == 0 && user->playing_moh) {
1252                 ast_moh_start(user->chan, user->u_profile.moh_class, NULL);
1253         }
1254         ao2_unlock(user->conference);
1255 }
1256
1257 /*!
1258  * \internal
1259  * \brief Suspend MOH for the conference user.
1260  *
1261  * \param user Conference user to suspend MOH on.
1262  *
1263  * \return Nothing
1264  */
1265 static void conf_moh_suspend(struct confbridge_user *user)
1266 {
1267         ao2_lock(user->conference);
1268         if (user->suspended_moh++ == 0 && user->playing_moh) {
1269                 ast_moh_stop(user->chan);
1270         }
1271         ao2_unlock(user->conference);
1272 }
1273
1274 int conf_handle_inactive_waitmarked(struct confbridge_user *user)
1275 {
1276         /* If we have not been quieted play back that they are waiting for the leader */
1277         if (!ast_test_flag(&user->u_profile, USER_OPT_QUIET) && play_prompt_to_user(user,
1278                         conf_get_sound(CONF_SOUND_WAIT_FOR_LEADER, user->conference->b_profile.sounds))) {
1279                 /* user hungup while the sound was playing */
1280                 return -1;
1281         }
1282         return 0;
1283 }
1284
1285 int conf_handle_only_unmarked(struct confbridge_user *user)
1286 {
1287         /* If audio prompts have not been quieted or this prompt quieted play it on out */
1288         if (!ast_test_flag(&user->u_profile, USER_OPT_QUIET | USER_OPT_NOONLYPERSON)) {
1289                 if (play_prompt_to_user(user,
1290                         conf_get_sound(CONF_SOUND_ONLY_PERSON, user->conference->b_profile.sounds))) {
1291                         /* user hungup while the sound was playing */
1292                         return -1;
1293                 }
1294         }
1295         return 0;
1296 }
1297
1298 int conf_add_post_join_action(struct confbridge_user *user, int (*func)(struct confbridge_user *user))
1299 {
1300         struct post_join_action *action;
1301         if (!(action = ast_calloc(1, sizeof(*action)))) {
1302                 return -1;
1303         }
1304         action->func = func;
1305         AST_LIST_INSERT_TAIL(&user->post_join_list, action, list);
1306         return 0;
1307 }
1308
1309
1310 void conf_handle_first_join(struct confbridge_conference *conference)
1311 {
1312         ast_devstate_changed(AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, "confbridge:%s", conference->name);
1313 }
1314
1315 void conf_handle_second_active(struct confbridge_conference *conference)
1316 {
1317         /* If we are the second participant we may need to stop music on hold on the first */
1318         struct confbridge_user *first_user = AST_LIST_FIRST(&conference->active_list);
1319
1320         if (ast_test_flag(&first_user->u_profile, USER_OPT_MUSICONHOLD)) {
1321                 conf_moh_stop(first_user);
1322         }
1323         conf_update_user_mute(first_user);
1324 }
1325
1326 void conf_ended(struct confbridge_conference *conference)
1327 {
1328         struct pbx_find_info q = { .stacklen = 0 };
1329
1330         /* Called with a reference to conference */
1331         ao2_unlink(conference_bridges, conference);
1332         send_conf_end_event(conference);
1333         if (!ast_strlen_zero(conference->b_profile.regcontext) &&
1334                         pbx_find_extension(NULL, NULL, &q, conference->b_profile.regcontext,
1335                                 conference->name, 1, NULL, "", E_MATCH)) {
1336                 ast_context_remove_extension(conference->b_profile.regcontext,
1337                                 conference->name, 1, NULL);
1338         }
1339         ao2_lock(conference);
1340         conf_stop_record(conference);
1341         ao2_unlock(conference);
1342 }
1343
1344 /*!
1345  * \internal
1346  * \brief Allocate playback channel for a conference.
1347  * \pre expects conference to be locked before calling this function
1348  */
1349 static int alloc_playback_chan(struct confbridge_conference *conference)
1350 {
1351         struct ast_format_cap *cap;
1352         char taskprocessor_name[AST_TASKPROCESSOR_MAX_NAME + 1];
1353
1354         cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
1355         if (!cap) {
1356                 return -1;
1357         }
1358         ast_format_cap_append(cap, ast_format_slin, 0);
1359         conference->playback_chan = ast_request("CBAnn", cap, NULL, NULL,
1360                 conference->name, NULL);
1361         ao2_ref(cap, -1);
1362         if (!conference->playback_chan) {
1363                 return -1;
1364         }
1365
1366         /* To make sure playback_chan has the same language as the bridge */
1367         ast_channel_lock(conference->playback_chan);
1368         ast_channel_language_set(conference->playback_chan, conference->b_profile.language);
1369         ast_channel_unlock(conference->playback_chan);
1370
1371         ast_debug(1, "Created announcer channel '%s' to conference bridge '%s'\n",
1372                 ast_channel_name(conference->playback_chan), conference->name);
1373
1374         ast_taskprocessor_build_name(taskprocessor_name, sizeof(taskprocessor_name),
1375                 "Confbridge/%s", conference->name);
1376         conference->playback_queue = ast_taskprocessor_get(taskprocessor_name, TPS_REF_DEFAULT);
1377         if (!conference->playback_queue) {
1378                 ast_hangup(conference->playback_chan);
1379                 conference->playback_chan = NULL;
1380                 return -1;
1381         }
1382         return 0;
1383 }
1384
1385 /*!
1386  * \brief Push the announcer channel into the bridge
1387  *
1388  * This runs in the playback queue taskprocessor.
1389  *
1390  * \param data A confbridge_conference
1391  * \retval 0 Success
1392  * \retval -1 Failed to push the channel to the bridge
1393  */
1394 static int push_announcer(void *data)
1395 {
1396         struct confbridge_conference *conference = data;
1397
1398         if (conf_announce_channel_push(conference->playback_chan)) {
1399                 ast_hangup(conference->playback_chan);
1400                 conference->playback_chan = NULL;
1401                 ao2_cleanup(conference);
1402                 return -1;
1403         }
1404
1405         ast_autoservice_start(conference->playback_chan);
1406         ao2_cleanup(conference);
1407         return 0;
1408 }
1409
1410 /*!
1411  * \brief Join a conference bridge
1412  *
1413  * \param conference_name The conference name
1414  * \param user Conference bridge user structure
1415  *
1416  * \return A pointer to the conference bridge struct, or NULL if the conference room wasn't found.
1417  */
1418 static struct confbridge_conference *join_conference_bridge(const char *conference_name, struct confbridge_user *user)
1419 {
1420         struct confbridge_conference *conference;
1421         struct post_join_action *action;
1422         int max_members_reached = 0;
1423
1424         /* We explictly lock the conference bridges container ourselves so that other callers can not create duplicate conferences at the same */
1425         ao2_lock(conference_bridges);
1426
1427         ast_debug(1, "Trying to find conference bridge '%s'\n", conference_name);
1428
1429         /* Attempt to find an existing conference bridge */
1430         conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
1431         if (conference && conference->b_profile.max_members) {
1432                 max_members_reached = conference->b_profile.max_members > conference->activeusers ? 0 : 1;
1433         }
1434
1435         /* When finding a conference bridge that already exists make sure that it is not locked, and if so that we are not an admin */
1436         if (conference && (max_members_reached || conference->locked) && !ast_test_flag(&user->u_profile, USER_OPT_ADMIN)) {
1437                 ao2_unlock(conference_bridges);
1438                 ast_debug(1, "Conference '%s' is locked and caller is not an admin\n", conference_name);
1439                 ast_stream_and_wait(user->chan,
1440                         conf_get_sound(CONF_SOUND_LOCKED, conference->b_profile.sounds),
1441                         "");
1442                 ao2_ref(conference, -1);
1443                 return NULL;
1444         }
1445
1446         /* If no conference bridge was found see if we can create one */
1447         if (!conference) {
1448                 /* Try to allocate memory for a new conference bridge, if we fail... this won't end well. */
1449                 if (!(conference = ao2_alloc(sizeof(*conference), destroy_conference_bridge))) {
1450                         ao2_unlock(conference_bridges);
1451                         ast_log(LOG_ERROR, "Conference '%s' could not be created.\n", conference_name);
1452                         return NULL;
1453                 }
1454
1455                 /* Setup for the record channel */
1456                 conference->record_filename = ast_str_create(RECORD_FILENAME_INITIAL_SPACE);
1457                 if (!conference->record_filename) {
1458                         ao2_ref(conference, -1);
1459                         ao2_unlock(conference_bridges);
1460                         return NULL;
1461                 }
1462
1463                 /* Setup conference bridge parameters */
1464                 ast_copy_string(conference->name, conference_name, sizeof(conference->name));
1465                 conf_bridge_profile_copy(&conference->b_profile, &user->b_profile);
1466
1467                 /* Create an actual bridge that will do the audio mixing */
1468                 conference->bridge = ast_bridge_base_new(AST_BRIDGE_CAPABILITY_MULTIMIX,
1469                         AST_BRIDGE_FLAG_MASQUERADE_ONLY | AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY,
1470                         app, conference_name, NULL);
1471                 if (!conference->bridge) {
1472                         ao2_ref(conference, -1);
1473                         ao2_unlock(conference_bridges);
1474                         ast_log(LOG_ERROR, "Conference '%s' mixing bridge could not be created.\n", conference_name);
1475                         return NULL;
1476                 }
1477
1478                 /* Set the internal sample rate on the bridge from the bridge profile */
1479                 ast_bridge_set_internal_sample_rate(conference->bridge, conference->b_profile.internal_sample_rate);
1480                 /* Set the internal mixing interval on the bridge from the bridge profile */
1481                 ast_bridge_set_mixing_interval(conference->bridge, conference->b_profile.mix_interval);
1482                 ast_bridge_set_binaural_active(conference->bridge, ast_test_flag(&conference->b_profile, BRIDGE_OPT_BINAURAL_ACTIVE));
1483
1484                 if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER)) {
1485                         ast_bridge_set_talker_src_video_mode(conference->bridge);
1486                 } else if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_VIDEO_SRC_SFU)) {
1487                         ast_bridge_set_sfu_video_mode(conference->bridge);
1488                 }
1489
1490                 /* Link it into the conference bridges container */
1491                 if (!ao2_link(conference_bridges, conference)) {
1492                         ao2_ref(conference, -1);
1493                         ao2_unlock(conference_bridges);
1494                         ast_log(LOG_ERROR,
1495                                 "Conference '%s' could not be added to the conferences list.\n", conference_name);
1496                         return NULL;
1497                 }
1498
1499                 /* Set the initial state to EMPTY */
1500                 conference->state = CONF_STATE_EMPTY;
1501
1502                 if (alloc_playback_chan(conference)) {
1503                         ao2_unlink(conference_bridges, conference);
1504                         ao2_ref(conference, -1);
1505                         ao2_unlock(conference_bridges);
1506                         ast_log(LOG_ERROR, "Could not allocate announcer channel for conference '%s'\n", conference_name);
1507                         return NULL;
1508                 }
1509
1510                 if (ast_taskprocessor_push(conference->playback_queue, push_announcer, ao2_bump(conference))) {
1511                         ao2_unlink(conference_bridges, conference);
1512                         ao2_ref(conference, -1);
1513                         ao2_unlock(conference_bridges);
1514                         ast_log(LOG_ERROR, "Could not add announcer channel for conference '%s' bridge\n", conference_name);
1515                         return NULL;
1516                 }
1517
1518                 if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_RECORD_CONFERENCE)) {
1519                         ao2_lock(conference);
1520                         conf_start_record(conference);
1521                         ao2_unlock(conference);
1522                 }
1523
1524                 send_conf_start_event(conference);
1525
1526                 if (!ast_strlen_zero(conference->b_profile.regcontext)) {
1527                         if (!ast_exists_extension(NULL, conference->b_profile.regcontext, conference->name, 1, NULL)) {
1528                                 ast_add_extension(conference->b_profile.regcontext, 1, conference->name, 1, NULL, NULL, "Noop", NULL, NULL, "ConfBridge");
1529                         }
1530                 }
1531
1532                 ast_debug(1, "Created conference '%s' and linked to container.\n", conference_name);
1533         }
1534
1535         ao2_unlock(conference_bridges);
1536
1537         /* Setup conference bridge user parameters */
1538         user->conference = conference;
1539
1540         ao2_lock(conference);
1541
1542         /* Determine if the new user should join the conference muted. */
1543         if (ast_test_flag(&user->u_profile, USER_OPT_STARTMUTED)
1544                 || (!ast_test_flag(&user->u_profile, USER_OPT_ADMIN) && conference->muted)) {
1545                 /* Set user level mute request. */
1546                 user->muted = 1;
1547         }
1548
1549         /*
1550          * Suspend any MOH until the user actually joins the bridge of
1551          * the conference.  This way any pre-join file playback does not
1552          * need to worry about MOH.
1553          */
1554         user->suspended_moh = 1;
1555
1556         if (handle_conf_user_join(user)) {
1557                 /* Invalid event, nothing was done, so we don't want to process a leave. */
1558                 ao2_unlock(conference);
1559                 ao2_ref(conference, -1);
1560                 user->conference = NULL;
1561                 return NULL;
1562         }
1563
1564         if (ast_check_hangup(user->chan)) {
1565                 ao2_unlock(conference);
1566                 leave_conference(user);
1567                 return NULL;
1568         }
1569
1570         ao2_unlock(conference);
1571
1572         /* If an announcement is to be played play it */
1573         if (!ast_strlen_zero(user->u_profile.announcement)) {
1574                 if (play_prompt_to_user(user,
1575                         user->u_profile.announcement)) {
1576                         leave_conference(user);
1577                         return NULL;
1578                 }
1579         }
1580
1581         /* Announce number of users if need be */
1582         if (ast_test_flag(&user->u_profile, USER_OPT_ANNOUNCEUSERCOUNT)) {
1583                 if (announce_user_count(conference, user, NULL)) {
1584                         leave_conference(user);
1585                         return NULL;
1586                 }
1587         }
1588
1589         if (ast_test_flag(&user->u_profile, USER_OPT_ANNOUNCEUSERCOUNTALL) &&
1590                 (conference->activeusers > user->u_profile.announce_user_count_all_after)) {
1591                 int user_count_res;
1592
1593                 /*
1594                  * We have to autoservice the new user because he has not quite
1595                  * joined the conference yet.
1596                  */
1597                 ast_autoservice_start(user->chan);
1598                 user_count_res = announce_user_count(conference, NULL, NULL);
1599                 ast_autoservice_stop(user->chan);
1600                 if (user_count_res) {
1601                         leave_conference(user);
1602                         return NULL;
1603                 }
1604         }
1605
1606         /* Handle post-join actions */
1607         while ((action = AST_LIST_REMOVE_HEAD(&user->post_join_list, list))) {
1608                 action->func(user);
1609                 ast_free(action);
1610         }
1611
1612         return conference;
1613 }
1614
1615 /*!
1616  * \brief Leave a conference
1617  *
1618  * \param user The conference user
1619  */
1620 static void leave_conference(struct confbridge_user *user)
1621 {
1622         struct post_join_action *action;
1623
1624         ao2_lock(user->conference);
1625         handle_conf_user_leave(user);
1626         ao2_unlock(user->conference);
1627
1628         /* Discard any post-join actions */
1629         while ((action = AST_LIST_REMOVE_HEAD(&user->post_join_list, list))) {
1630                 ast_free(action);
1631         }
1632
1633         /* Done mucking with the conference, huzzah */
1634         ao2_ref(user->conference, -1);
1635         user->conference = NULL;
1636 }
1637
1638 static void playback_common(struct confbridge_conference *conference, const char *filename, int say_number)
1639 {
1640         /* Don't try to play if the playback channel has been hung up */
1641         if (!conference->playback_chan) {
1642                 return;
1643         }
1644
1645         ast_autoservice_stop(conference->playback_chan);
1646
1647         /* The channel is all under our control, in goes the prompt */
1648         if (!ast_strlen_zero(filename)) {
1649                 ast_stream_and_wait(conference->playback_chan, filename, "");
1650         } else if (say_number >= 0) {
1651                 ast_say_number(conference->playback_chan, say_number, "",
1652                         ast_channel_language(conference->playback_chan), NULL);
1653         }
1654
1655         ast_autoservice_start(conference->playback_chan);
1656 }
1657
1658 struct playback_task_data {
1659         struct confbridge_conference *conference;
1660         const char *filename;
1661         int say_number;
1662         int playback_finished;
1663         ast_mutex_t lock;
1664         ast_cond_t cond;
1665 };
1666
1667 /*!
1668  * \brief Play an announcement into a confbridge
1669  *
1670  * This runs in the playback queue taskprocessor. This ensures that
1671  * all playbacks are handled in sequence and do not play over top one
1672  * another.
1673  *
1674  * This task runs synchronously so there is no need for performing any
1675  * sort of cleanup on the input parameter.
1676  *
1677  * \param data A playback_task_data
1678  * \return 0
1679  */
1680 static int playback_task(void *data)
1681 {
1682         struct playback_task_data *ptd = data;
1683
1684         playback_common(ptd->conference, ptd->filename, ptd->say_number);
1685
1686         ast_mutex_lock(&ptd->lock);
1687         ptd->playback_finished = 1;
1688         ast_cond_signal(&ptd->cond);
1689         ast_mutex_unlock(&ptd->lock);
1690
1691         return 0;
1692 }
1693
1694 static void playback_task_data_init(struct playback_task_data *ptd, struct confbridge_conference *conference,
1695                 const char *filename, int say_number)
1696 {
1697         ast_mutex_init(&ptd->lock);
1698         ast_cond_init(&ptd->cond, NULL);
1699
1700         ptd->filename = filename;
1701         ptd->say_number = say_number;
1702         ptd->conference = conference;
1703         ptd->playback_finished = 0;
1704 }
1705
1706 static void playback_task_data_destroy(struct playback_task_data *ptd)
1707 {
1708         ast_mutex_destroy(&ptd->lock);
1709         ast_cond_destroy(&ptd->cond);
1710 }
1711
1712 static int play_sound_helper(struct confbridge_conference *conference, const char *filename, int say_number)
1713 {
1714         struct playback_task_data ptd;
1715
1716         /* Do not waste resources trying to play files that do not exist */
1717         if (ast_strlen_zero(filename)) {
1718                 if (say_number < 0) {
1719                         return 0;
1720                 }
1721         } else if (!sound_file_exists(filename)) {
1722                 return 0;
1723         }
1724
1725         playback_task_data_init(&ptd, conference, filename, say_number);
1726         if (ast_taskprocessor_push(conference->playback_queue, playback_task, &ptd)) {
1727                 if (!ast_strlen_zero(filename)) {
1728                         ast_log(LOG_WARNING, "Unable to play file '%s' to conference %s\n",
1729                                 filename, conference->name);
1730                 } else {
1731                         ast_log(LOG_WARNING, "Unable to say number '%d' to conference %s\n",
1732                                 say_number, conference->name);
1733                 }
1734                 playback_task_data_destroy(&ptd);
1735                 return -1;
1736         }
1737
1738         /* Wait for the playback to complete */
1739         ast_mutex_lock(&ptd.lock);
1740         while (!ptd.playback_finished) {
1741                 ast_cond_wait(&ptd.cond, &ptd.lock);
1742         }
1743         ast_mutex_unlock(&ptd.lock);
1744
1745         playback_task_data_destroy(&ptd);
1746
1747         return 0;
1748 }
1749
1750 int play_sound_file(struct confbridge_conference *conference, const char *filename)
1751 {
1752         return play_sound_helper(conference, filename, -1);
1753 }
1754
1755 struct async_playback_task_data {
1756         struct confbridge_conference *conference;
1757         int say_number;
1758         struct ast_channel *initiator;
1759         char filename[0];
1760 };
1761
1762 struct async_datastore_data {
1763         ast_mutex_t lock;
1764         ast_cond_t cond;
1765         int wait;
1766 };
1767
1768 static void async_datastore_data_destroy(void *data)
1769 {
1770         struct async_datastore_data *add = data;
1771
1772         ast_mutex_destroy(&add->lock);
1773         ast_cond_destroy(&add->cond);
1774
1775         ast_free(add);
1776 }
1777
1778 /*!
1779  * \brief Datastore used for timing of async announcement playback
1780  *
1781  * Announcements that are played to the entire conference can be played
1782  * asynchronously (i.e. The channel that queues the playback does not wait
1783  * for the playback to complete before continuing)
1784  *
1785  * The thing about async announcements is that the channel that queues the
1786  * announcement is either not in the bridge or is in some other way "occupied"
1787  * at the time the announcement is queued. Because of that, the initiator of
1788  * the announcement may enter after the announcement has already started,
1789  * resulting in the sound being "clipped".
1790  *
1791  * This datastore makes it so that the channel that queues the async announcement
1792  * can say "I'm ready now". This way the announcement does not start until the
1793  * initiator of the announcement is ready to hear the sound.
1794  */
1795 static struct ast_datastore_info async_datastore_info = {
1796         .type = "Confbridge async playback",
1797         .destroy = async_datastore_data_destroy,
1798 };
1799
1800 static struct async_datastore_data *async_datastore_data_alloc(void)
1801 {
1802         struct async_datastore_data *add;
1803
1804         add = ast_malloc(sizeof(*add));
1805         if (!add) {
1806                 return NULL;
1807         }
1808
1809         ast_mutex_init(&add->lock);
1810         ast_cond_init(&add->cond, NULL);
1811         add->wait = 1;
1812
1813         return add;
1814 }
1815
1816 /*!
1817  * \brief Prepare the async playback datastore
1818  *
1819  * This is done prior to queuing an async announcement. If the
1820  * datastore has not yet been created, it is allocated and initialized.
1821  * If it already exists, we set it to be in "waiting" mode.
1822  *
1823  * \param initiator The channel that is queuing the async playback
1824  * \retval 0 Success
1825  * \retval -1 Failure :(
1826  */
1827 static int setup_async_playback_datastore(struct ast_channel *initiator)
1828 {
1829         struct ast_datastore *async_datastore;
1830
1831         async_datastore = ast_channel_datastore_find(initiator, &async_datastore_info, NULL);
1832         if (async_datastore) {
1833                 struct async_datastore_data *add;
1834
1835                 add = async_datastore->data;
1836                 add->wait = 1;
1837
1838                 return 0;
1839         }
1840
1841         async_datastore = ast_datastore_alloc(&async_datastore_info, NULL);
1842         if (!async_datastore) {
1843                 return -1;
1844         }
1845
1846         async_datastore->data = async_datastore_data_alloc();
1847         if (!async_datastore->data) {
1848                 ast_datastore_free(async_datastore);
1849                 return -1;
1850         }
1851
1852         ast_channel_datastore_add(initiator, async_datastore);
1853         return 0;
1854 }
1855
1856 static struct async_playback_task_data *async_playback_task_data_alloc(
1857         struct confbridge_conference *conference, const char *filename, int say_number,
1858         struct ast_channel *initiator)
1859 {
1860         struct async_playback_task_data *aptd;
1861
1862         aptd = ast_malloc(sizeof(*aptd) + strlen(filename) + 1);
1863         if (!aptd) {
1864                 return NULL;
1865         }
1866
1867         /* Safe */
1868         strcpy(aptd->filename, filename);
1869         aptd->say_number = say_number;
1870
1871         /* You may think that we need to bump the conference refcount since we are pushing
1872          * this task to the taskprocessor.
1873          *
1874          * In this case, that actually causes a problem. The destructor for the conference
1875          * pushes a hangup task into the taskprocessor and waits for it to complete before
1876          * continuing. If the destructor gets called from a taskprocessor task, we're
1877          * deadlocked.
1878          *
1879          * So is there a risk of the conference being freed out from under us? No. Since
1880          * the destructor pushes a task into the taskprocessor and waits for it to complete,
1881          * the destructor cannot free the conference out from under us. No further tasks
1882          * can be queued onto the taskprocessor after the hangup since no channels are referencing
1883          * the conference at that point any more.
1884          */
1885         aptd->conference = conference;
1886
1887         aptd->initiator = initiator;
1888         if (initiator) {
1889                 ast_channel_ref(initiator);
1890                 ast_channel_lock(aptd->initiator);
1891                 /* We don't really care if this fails. If the datastore fails to get set up
1892                  * we'll still play the announcement. It's possible that the sound will be
1893                  * clipped for the initiator, but that's not the end of the world.
1894                  */
1895                 setup_async_playback_datastore(aptd->initiator);
1896                 ast_channel_unlock(aptd->initiator);
1897         }
1898
1899         return aptd;
1900 }
1901
1902 static void async_playback_task_data_destroy(struct async_playback_task_data *aptd)
1903 {
1904         ast_channel_cleanup(aptd->initiator);
1905         ast_free(aptd);
1906 }
1907
1908 /*!
1909  * \brief Wait for the initiator of an async playback to be ready
1910  *
1911  * See the description on the async_datastore_info structure for more
1912  * information about what this is about.
1913  *
1914  * \param initiator The channel that queued the async announcement
1915  */
1916 static void wait_for_initiator(struct ast_channel *initiator)
1917 {
1918         struct ast_datastore *async_datastore;
1919         struct async_datastore_data *add;
1920
1921         ast_channel_lock(initiator);
1922         async_datastore = ast_channel_datastore_find(initiator, &async_datastore_info, NULL);
1923         ast_channel_unlock(initiator);
1924
1925         if (!async_datastore) {
1926                 return;
1927         }
1928
1929         add = async_datastore->data;
1930
1931         ast_mutex_lock(&add->lock);
1932         while (add->wait) {
1933                 ast_cond_wait(&add->cond, &add->lock);
1934         }
1935         ast_mutex_unlock(&add->lock);
1936 }
1937
1938 /*!
1939  * \brief Play an announcement into a confbridge asynchronously
1940  *
1941  * This runs in the playback queue taskprocessor. This ensures that
1942  * all playbacks are handled in sequence and do not play over top one
1943  * another.
1944  *
1945  * \param data An async_playback_task_data
1946  * \return 0
1947  */
1948 static int async_playback_task(void *data)
1949 {
1950         struct async_playback_task_data *aptd = data;
1951
1952         /* Wait for the initiator to get back in the bridge or be hung up */
1953         if (aptd->initiator) {
1954                 wait_for_initiator(aptd->initiator);
1955         }
1956
1957         playback_common(aptd->conference, aptd->filename, aptd->say_number);
1958
1959         async_playback_task_data_destroy(aptd);
1960         return 0;
1961 }
1962
1963 static int async_play_sound_helper(struct confbridge_conference *conference,
1964         const char *filename, int say_number, struct ast_channel *initiator)
1965 {
1966         struct async_playback_task_data *aptd;
1967
1968         /* Do not waste resources trying to play files that do not exist */
1969         if (ast_strlen_zero(filename)) {
1970                 if (say_number < 0) {
1971                         return 0;
1972                 }
1973         } else if (!sound_file_exists(filename)) {
1974                 return 0;
1975         }
1976
1977         aptd = async_playback_task_data_alloc(conference, filename, say_number, initiator);
1978         if (!aptd) {
1979                 return -1;
1980         }
1981
1982         if (ast_taskprocessor_push(conference->playback_queue, async_playback_task, aptd)) {
1983                 if (!ast_strlen_zero(filename)) {
1984                         ast_log(LOG_WARNING, "Unable to play file '%s' to conference '%s'\n",
1985                                 filename, conference->name);
1986                 } else {
1987                         ast_log(LOG_WARNING, "Unable to say number '%d' to conference '%s'\n",
1988                                 say_number, conference->name);
1989                 }
1990                 async_playback_task_data_destroy(aptd);
1991                 return -1;
1992         }
1993
1994         return 0;
1995 }
1996
1997 int async_play_sound_file(struct confbridge_conference *conference,
1998         const char *filename, struct ast_channel *initiator)
1999 {
2000         return async_play_sound_helper(conference, filename, -1, initiator);
2001 }
2002
2003 void async_play_sound_ready(struct ast_channel *chan)
2004 {
2005         struct ast_datastore *async_datastore;
2006         struct async_datastore_data *add;
2007
2008         ast_channel_lock(chan);
2009         async_datastore = ast_channel_datastore_find(chan, &async_datastore_info, NULL);
2010         ast_channel_unlock(chan);
2011         if (!async_datastore) {
2012                 return;
2013         }
2014
2015         add = async_datastore->data;
2016
2017         ast_mutex_lock(&add->lock);
2018         add->wait = 0;
2019         ast_cond_signal(&add->cond);
2020         ast_mutex_unlock(&add->lock);
2021 }
2022
2023 /*!
2024  * \brief Play number into the conference bridge
2025  *
2026  * \param conference The conference bridge to say the number into
2027  * \param say_number number to say
2028  *
2029  * \retval 0 success
2030  * \retval -1 failure
2031  */
2032 static int play_sound_number(struct confbridge_conference *conference, int say_number)
2033 {
2034         return play_sound_helper(conference, NULL, say_number);
2035 }
2036
2037 static int conf_handle_talker_cb(struct ast_bridge_channel *bridge_channel, void *hook_pvt, int talking)
2038 {
2039         const struct confbridge_user *user = hook_pvt;
2040         RAII_VAR(struct confbridge_conference *, conference, NULL, ao2_cleanup);
2041         struct ast_json *talking_extras;
2042
2043         conference = ao2_find(conference_bridges, user->conference->name, OBJ_KEY);
2044         if (!conference) {
2045                 /* Remove the hook since the conference does not exist. */
2046                 return -1;
2047         }
2048
2049         talking_extras = ast_json_pack("{s: s, s: b}",
2050                 "talking_status", talking ? "on" : "off",
2051                 "admin", ast_test_flag(&user->u_profile, USER_OPT_ADMIN));
2052         if (!talking_extras) {
2053                 return 0;
2054         }
2055
2056         send_conf_stasis(conference, bridge_channel->chan, confbridge_talking_type(), talking_extras, 0);
2057         ast_json_unref(talking_extras);
2058         return 0;
2059 }
2060
2061 static int conf_get_pin(struct ast_channel *chan, struct confbridge_user *user)
2062 {
2063         char pin_guess[MAX_PIN+1] = { 0, };
2064         const char *pin = user->u_profile.pin;
2065         char *tmp = pin_guess;
2066         int i, res;
2067         unsigned int len = MAX_PIN;
2068
2069         /*
2070          * NOTE: We have not joined a conference yet so we have to use
2071          * the bridge profile requested by the user.
2072          */
2073
2074         /* give them three tries to get the pin right */
2075         for (i = 0; i < 3; i++) {
2076                 if (ast_app_getdata(chan,
2077                         conf_get_sound(CONF_SOUND_GET_PIN, user->b_profile.sounds),
2078                         tmp, len, 0) >= 0) {
2079                         if (!strcasecmp(pin, pin_guess)) {
2080                                 return 0;
2081                         }
2082                 }
2083                 ast_streamfile(chan,
2084                         conf_get_sound(CONF_SOUND_INVALID_PIN, user->b_profile.sounds),
2085                         ast_channel_language(chan));
2086                 res = ast_waitstream(chan, AST_DIGIT_ANY);
2087                 if (res > 0) {
2088                         /* Account for digit already read during ivalid pin playback
2089                          * resetting pin buf. */
2090                         pin_guess[0] = res;
2091                         pin_guess[1] = '\0';
2092                         tmp = pin_guess + 1;
2093                         len = MAX_PIN - 1;
2094                 } else {
2095                         /* reset pin buf as empty buffer. */
2096                         tmp = pin_guess;
2097                         len = MAX_PIN;
2098                 }
2099         }
2100         return -1;
2101 }
2102
2103 static int user_timeout(struct ast_bridge_channel *bridge_channel, void *ignore)
2104 {
2105         ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END, 0);
2106         pbx_builtin_setvar_helper(bridge_channel->chan, "CONFBRIDGE_RESULT", "TIMEOUT");
2107         return -1;
2108 }
2109
2110 static int conf_rec_name(struct confbridge_user *user, const char *conf_name)
2111 {
2112         char destdir[PATH_MAX];
2113         int res;
2114         int duration = 20;
2115
2116         snprintf(destdir, sizeof(destdir), "%s/confbridge", ast_config_AST_SPOOL_DIR);
2117
2118         if (ast_mkdir(destdir, 0777) != 0) {
2119                 ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", destdir, strerror(errno));
2120                 return -1;
2121         }
2122         snprintf(user->name_rec_location, sizeof(user->name_rec_location),
2123                  "%s/confbridge-name-%s-%s", destdir,
2124                  conf_name, ast_channel_uniqueid(user->chan));
2125
2126         if (!(ast_test_flag(&user->u_profile, USER_OPT_ANNOUNCE_JOIN_LEAVE_REVIEW))) {
2127                 res = ast_play_and_record(user->chan,
2128                         "vm-rec-name",
2129                         user->name_rec_location,
2130                         10,
2131                         "sln",
2132                         &duration,
2133                         NULL,
2134                         ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE),
2135                         0,
2136                         NULL);
2137         } else {
2138                 res = ast_record_review(user->chan,
2139                         "vm-rec-name",
2140                         user->name_rec_location,
2141                         10,
2142                         "sln",
2143                         &duration,
2144                         NULL);
2145         }
2146
2147         if (res == -1) {
2148                 user->name_rec_location[0] = '\0';
2149                 return -1;
2150         }
2151         return 0;
2152 }
2153
2154 static int join_callback(struct ast_bridge_channel *bridge_channel, void *ignore)
2155 {
2156         async_play_sound_ready(bridge_channel->chan);
2157         return 0;
2158 }
2159
2160 /*! \brief The ConfBridge application */
2161 static int confbridge_exec(struct ast_channel *chan, const char *data)
2162 {
2163         int res = 0, volume_adjustments[2];
2164         int quiet = 0;
2165         char *parse;
2166         const char *b_profile_name = NULL;
2167         const char *u_profile_name = NULL;
2168         const char *menu_profile_name = NULL;
2169         struct confbridge_conference *conference = NULL;
2170         struct confbridge_user user = {
2171                 .chan = chan,
2172                 .tech_args.talking_threshold = DEFAULT_TALKING_THRESHOLD,
2173                 .tech_args.silence_threshold = DEFAULT_SILENCE_THRESHOLD,
2174                 .tech_args.drop_silence = 0,
2175         };
2176         AST_DECLARE_APP_ARGS(args,
2177                 AST_APP_ARG(conf_name);
2178                 AST_APP_ARG(b_profile_name);
2179                 AST_APP_ARG(u_profile_name);
2180                 AST_APP_ARG(menu_profile_name);
2181         );
2182
2183         if (ast_channel_state(chan) != AST_STATE_UP) {
2184                 ast_answer(chan);
2185         }
2186
2187         if (ast_bridge_features_init(&user.features)) {
2188                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2189                 res = -1;
2190                 goto confbridge_cleanup;
2191         }
2192
2193         /* We need to make a copy of the input string if we are going to modify it! */
2194         parse = ast_strdupa(data);
2195
2196         AST_STANDARD_APP_ARGS(args, parse);
2197
2198         if (ast_strlen_zero(args.conf_name)) {
2199                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2200                 ast_log(LOG_WARNING, "%s requires an argument (conference name[,options])\n", app);
2201                 res = -1;
2202                 goto confbridge_cleanup;
2203         }
2204
2205         if (strlen(args.conf_name) >= MAX_CONF_NAME) {
2206                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2207                 ast_log(LOG_WARNING, "%s does not accept conference names longer than %d\n", app, MAX_CONF_NAME - 1);
2208                 res = -1;
2209                 goto confbridge_cleanup;
2210         }
2211
2212         /* bridge profile name */
2213         if (args.argc > 1 && !ast_strlen_zero(args.b_profile_name)) {
2214                 b_profile_name = args.b_profile_name;
2215         }
2216         if (!conf_find_bridge_profile(chan, b_profile_name, &user.b_profile)) {
2217                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2218                 ast_log(LOG_WARNING, "Conference bridge profile %s does not exist\n", b_profile_name ?
2219                         b_profile_name : DEFAULT_BRIDGE_PROFILE);
2220                 res = -1;
2221                 goto confbridge_cleanup;
2222         }
2223
2224         /* user profile name */
2225         if (args.argc > 2 && !ast_strlen_zero(args.u_profile_name)) {
2226                 u_profile_name = args.u_profile_name;
2227         }
2228         if (!conf_find_user_profile(chan, u_profile_name, &user.u_profile)) {
2229                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2230                 ast_log(LOG_WARNING, "Conference user profile %s does not exist\n", u_profile_name ?
2231                         u_profile_name : DEFAULT_USER_PROFILE);
2232                 res = -1;
2233                 goto confbridge_cleanup;
2234         }
2235
2236         quiet = ast_test_flag(&user.u_profile, USER_OPT_QUIET);
2237
2238         /* ask for a PIN immediately after finding user profile.  This has to be
2239          * prompted for requardless of quiet setting. */
2240         if (!ast_strlen_zero(user.u_profile.pin)) {
2241                 if (conf_get_pin(chan, &user)) {
2242                         pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2243                         res = -1; /* invalid PIN */
2244                         goto confbridge_cleanup;
2245                 }
2246         }
2247
2248         /* See if we need them to record a intro name */
2249         if (!quiet &&
2250                 (ast_test_flag(&user.u_profile, USER_OPT_ANNOUNCE_JOIN_LEAVE) ||
2251                 (ast_test_flag(&user.u_profile, USER_OPT_ANNOUNCE_JOIN_LEAVE_REVIEW)))) {
2252                 conf_rec_name(&user, args.conf_name);
2253         }
2254
2255         /* menu name */
2256         if (args.argc > 3 && !ast_strlen_zero(args.menu_profile_name)) {
2257                 menu_profile_name = args.menu_profile_name;
2258         }
2259
2260         if (conf_set_menu_to_user(chan, &user, menu_profile_name)) {
2261                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2262                 ast_log(LOG_WARNING, "Conference menu profile %s does not exist\n", menu_profile_name ?
2263                         menu_profile_name : DEFAULT_MENU_PROFILE);
2264                 res = -1;
2265                 goto confbridge_cleanup;
2266         }
2267
2268         /* Set if DTMF should pass through for this user or not */
2269         if (ast_test_flag(&user.u_profile, USER_OPT_DTMF_PASS)) {
2270                 user.features.dtmf_passthrough = 1;
2271         } else {
2272                 user.features.dtmf_passthrough = 0;
2273         }
2274
2275         /* Set dsp threshold values if present */
2276         if (user.u_profile.talking_threshold) {
2277                 user.tech_args.talking_threshold = user.u_profile.talking_threshold;
2278         }
2279         if (user.u_profile.silence_threshold) {
2280                 user.tech_args.silence_threshold = user.u_profile.silence_threshold;
2281         }
2282
2283         /* Set a talker indicate call back if talking detection is requested */
2284         if (ast_test_flag(&user.u_profile, USER_OPT_TALKER_DETECT)) {
2285                 if (ast_bridge_talk_detector_hook(&user.features, conf_handle_talker_cb,
2286                         &user, NULL, AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
2287                         pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2288                         res = -1;
2289                         goto confbridge_cleanup;
2290                 }
2291         }
2292
2293         /* Look for a conference bridge matching the provided name */
2294         if (!(conference = join_conference_bridge(args.conf_name, &user))) {
2295                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2296                 res = -1;
2297                 goto confbridge_cleanup;
2298         }
2299
2300         /* Keep a copy of volume adjustments so we can restore them later if need be */
2301         volume_adjustments[0] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_READ);
2302         volume_adjustments[1] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_WRITE);
2303
2304         if (ast_test_flag(&user.u_profile, USER_OPT_DROP_SILENCE)) {
2305                 user.tech_args.drop_silence = 1;
2306         }
2307
2308         if (ast_test_flag(&user.u_profile, USER_OPT_JITTERBUFFER)) {
2309                 char *func_jb;
2310                 if ((func_jb = ast_module_helper("", "func_jitterbuffer", 0, 0, 0, 0))) {
2311                         ast_free(func_jb);
2312                         ast_func_write(chan, "JITTERBUFFER(adaptive)", "default");
2313                 }
2314         }
2315
2316         if (ast_test_flag(&user.u_profile, USER_OPT_DENOISE)) {
2317                 char *mod_speex;
2318                 /* Reduce background noise from each participant */
2319                 if ((mod_speex = ast_module_helper("", "codec_speex", 0, 0, 0, 0))) {
2320                         ast_free(mod_speex);
2321                         ast_func_write(chan, "DENOISE(rx)", "on");
2322                 }
2323         }
2324
2325         /* if this user has a intro, play it before entering */
2326         if (!ast_strlen_zero(user.name_rec_location)) {
2327                 ast_autoservice_start(chan);
2328                 play_sound_file(conference, user.name_rec_location);
2329                 play_sound_file(conference,
2330                         conf_get_sound(CONF_SOUND_HAS_JOINED, conference->b_profile.sounds));
2331                 ast_autoservice_stop(chan);
2332         }
2333
2334         /* Play the Join sound to both the conference and the user entering. */
2335         if (!quiet) {
2336                 const char *join_sound = conf_get_sound(CONF_SOUND_JOIN, conference->b_profile.sounds);
2337
2338                 if (strcmp(conference->b_profile.language, ast_channel_language(chan))) {
2339                         ast_stream_and_wait(chan, join_sound, "");
2340                         ast_autoservice_start(chan);
2341                         play_sound_file(conference, join_sound);
2342                         ast_autoservice_stop(chan);
2343                 } else {
2344                         async_play_sound_file(conference, join_sound, chan);
2345                 }
2346         }
2347
2348         if (user.u_profile.timeout) {
2349                 ast_bridge_interval_hook(&user.features,
2350                         0,
2351                         user.u_profile.timeout * 1000,
2352                         user_timeout,
2353                         NULL,
2354                         NULL,
2355                         AST_BRIDGE_HOOK_REMOVE_ON_PULL);
2356         }
2357
2358         /* See if we need to automatically set this user as a video source or not */
2359         handle_video_on_join(conference, user.chan, ast_test_flag(&user.u_profile, USER_OPT_MARKEDUSER));
2360
2361         conf_moh_unsuspend(&user);
2362
2363         /* Join our conference bridge for real */
2364         send_join_event(&user, conference);
2365
2366         if (ast_bridge_join_hook(&user.features, join_callback, NULL, NULL, 0)) {
2367                 async_play_sound_ready(user.chan);
2368         }
2369
2370         ast_bridge_join(conference->bridge,
2371                 chan,
2372                 NULL,
2373                 &user.features,
2374                 &user.tech_args,
2375                 0);
2376
2377         /* This is a catch-all in case joining the bridge failed or for some reason
2378          * an async announcement got queued up and hasn't been told to play yet
2379          */
2380         async_play_sound_ready(chan);
2381
2382         if (!user.kicked && ast_check_hangup(chan)) {
2383                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "HANGUP");
2384         }
2385
2386         send_leave_event(&user, conference);
2387
2388         /* if we're shutting down, don't attempt to do further processing */
2389         if (ast_shutting_down()) {
2390                 /*
2391                  * Not taking any new calls at this time.  We cannot create
2392                  * the announcer channel if this is the first channel into
2393                  * the conference and we certainly cannot create any
2394                  * recording channel.
2395                  */
2396                 leave_conference(&user);
2397                 conference = NULL;
2398                 goto confbridge_cleanup;
2399         }
2400
2401         /* If this user was a video source, we need to clean up and possibly pick a new source. */
2402         handle_video_on_exit(conference, user.chan);
2403
2404         /* if this user has a intro, play it when leaving */
2405         if (!quiet && !ast_strlen_zero(user.name_rec_location)) {
2406                 async_play_sound_file(conference, user.name_rec_location, NULL);
2407                 async_play_sound_file(conference,
2408                         conf_get_sound(CONF_SOUND_HAS_LEFT, conference->b_profile.sounds), NULL);
2409         }
2410
2411         /* play the leave sound */
2412         if (!quiet) {
2413                 const char *leave_sound = conf_get_sound(CONF_SOUND_LEAVE, conference->b_profile.sounds);
2414                 async_play_sound_file(conference, leave_sound, NULL);
2415         }
2416
2417         /* If the user was kicked from the conference play back the audio prompt for it */
2418         if (!quiet && user.kicked) {
2419                 res = ast_stream_and_wait(chan,
2420                         conf_get_sound(CONF_SOUND_KICKED, conference->b_profile.sounds),
2421                         "");
2422         }
2423
2424         /* Easy as pie, depart this channel from the conference bridge */
2425         leave_conference(&user);
2426         conference = NULL;
2427
2428         /* Restore volume adjustments to previous values in case they were changed */
2429         if (volume_adjustments[0]) {
2430                 ast_audiohook_volume_set(chan, AST_AUDIOHOOK_DIRECTION_READ, volume_adjustments[0]);
2431         }
2432         if (volume_adjustments[1]) {
2433                 ast_audiohook_volume_set(chan, AST_AUDIOHOOK_DIRECTION_WRITE, volume_adjustments[1]);
2434         }
2435
2436         if (!ast_strlen_zero(user.name_rec_location)) {
2437                 ast_filedelete(user.name_rec_location, NULL);
2438         }
2439
2440 confbridge_cleanup:
2441         ast_bridge_features_cleanup(&user.features);
2442         conf_bridge_profile_destroy(&user.b_profile);
2443         return res;
2444 }
2445
2446 static int action_toggle_mute(struct confbridge_conference *conference,
2447                               struct confbridge_user *user,
2448                               struct ast_bridge_channel *bridge_channel)
2449 {
2450         int mute;
2451
2452         /* Toggle user level mute request. */
2453         mute = !user->muted;
2454         generic_mute_unmute_user(conference, user, mute);
2455
2456         return play_file(bridge_channel, NULL,
2457                 conf_get_sound(mute ? CONF_SOUND_MUTED : CONF_SOUND_UNMUTED,
2458                         conference->b_profile.sounds)) < 0;
2459 }
2460
2461 static int action_toggle_binaural(struct confbridge_conference *conference,
2462                 struct confbridge_user *user,
2463                 struct ast_bridge_channel *bridge_channel)
2464 {
2465         unsigned int binaural;
2466         ast_bridge_channel_lock_bridge(bridge_channel);
2467         binaural = !bridge_channel->binaural_suspended;
2468         bridge_channel->binaural_suspended = binaural;
2469         ast_bridge_unlock(bridge_channel->bridge);
2470         return play_file(bridge_channel, NULL, (binaural ?
2471                                 conf_get_sound(CONF_SOUND_BINAURAL_OFF, user->b_profile.sounds) :
2472                                 conf_get_sound(CONF_SOUND_BINAURAL_ON, user->b_profile.sounds))) < 0;
2473 }
2474
2475 static int action_toggle_mute_participants(struct confbridge_conference *conference, struct confbridge_user *user)
2476 {
2477         struct confbridge_user *cur_user = NULL;
2478         const char *sound_to_play;
2479         int mute;
2480
2481         ao2_lock(conference);
2482
2483         /* Toggle bridge level mute request. */
2484         mute = !conference->muted;
2485         conference->muted = mute;
2486
2487         AST_LIST_TRAVERSE(&conference->active_list, cur_user, list) {
2488                 if (!ast_test_flag(&cur_user->u_profile, USER_OPT_ADMIN)) {
2489                         /* Set user level to bridge level mute request. */
2490                         cur_user->muted = mute;
2491                         conf_update_user_mute(cur_user);
2492                 }
2493         }
2494
2495         ao2_unlock(conference);
2496
2497         sound_to_play = conf_get_sound(
2498                 mute ? CONF_SOUND_PARTICIPANTS_MUTED : CONF_SOUND_PARTICIPANTS_UNMUTED,
2499                 conference->b_profile.sounds);
2500
2501         if (strcmp(conference->b_profile.language, ast_channel_language(user->chan))) {
2502                 /* The host needs to hear it seperately, as they don't get the audio from play_sound_helper */
2503                 ast_stream_and_wait(user->chan, sound_to_play, "");
2504
2505                 /* Announce to the group that all participants are muted */
2506                 ast_autoservice_start(user->chan);
2507                 play_sound_file(conference, sound_to_play);
2508                 ast_autoservice_stop(user->chan);
2509         } else {
2510                 /* Playing the sound asynchronously lets the sound be heard by everyone at once */
2511                 async_play_sound_file(conference, sound_to_play, user->chan);
2512         }
2513
2514         return 0;
2515 }
2516
2517 static int action_playback(struct ast_bridge_channel *bridge_channel, const char *playback_file)
2518 {
2519         char *file_copy = ast_strdupa(playback_file);
2520         char *file = NULL;
2521
2522         while ((file = strsep(&file_copy, "&"))) {
2523                 if (ast_stream_and_wait(bridge_channel->chan, file, "")) {
2524                         ast_log(LOG_WARNING, "Failed to playback file %s to channel\n", file);
2525                         return -1;
2526                 }
2527         }
2528         return 0;
2529 }
2530
2531 static int action_playback_and_continue(struct confbridge_conference *conference,
2532         struct confbridge_user *user,
2533         struct ast_bridge_channel *bridge_channel,
2534         struct conf_menu *menu,
2535         const char *playback_file,
2536         const char *cur_dtmf,
2537         int *stop_prompts)
2538 {
2539         int i;
2540         int digit = 0;
2541         char dtmf[MAXIMUM_DTMF_FEATURE_STRING];
2542         struct conf_menu_entry new_menu_entry = { { 0, }, };
2543         char *file_copy = ast_strdupa(playback_file);
2544         char *file = NULL;
2545
2546         while ((file = strsep(&file_copy, "&"))) {
2547                 if (ast_streamfile(bridge_channel->chan, file, ast_channel_language(bridge_channel->chan))) {
2548                         ast_log(LOG_WARNING, "Failed to playback file %s to channel\n", file);
2549                         return -1;
2550                 }
2551
2552                 /* now wait for more digits. */
2553                 if (!(digit = ast_waitstream(bridge_channel->chan, AST_DIGIT_ANY))) {
2554                         /* streaming finished and no DTMF was entered */
2555                         continue;
2556                 } else if (digit == -1) {
2557                         /* error */
2558                         return -1;
2559                 } else {
2560                         break; /* dtmf was entered */
2561                 }
2562         }
2563         if (!digit) {
2564                 /* streaming finished on all files and no DTMF was entered */
2565                 return -1;
2566         }
2567         ast_stopstream(bridge_channel->chan);
2568
2569         /* If we get here, then DTMF has been entered, This means no
2570          * additional prompts should be played for this menu entry */
2571         *stop_prompts = 1;
2572
2573         /* If a digit was pressed during the payback, update
2574          * the dtmf string and look for a new menu entry in the
2575          * menu structure */
2576         ast_copy_string(dtmf, cur_dtmf, sizeof(dtmf));
2577         for (i = 0; i < (MAXIMUM_DTMF_FEATURE_STRING - 1); i++) {
2578                 dtmf[i] = cur_dtmf[i];
2579                 if (!dtmf[i]) {
2580                         dtmf[i] = (char) digit;
2581                         dtmf[i + 1] = '\0';
2582                         i = -1;
2583                         break;
2584                 }
2585         }
2586         /* If i is not -1 then the new dtmf digit was _NOT_ added to the string.
2587          * If this is the case, no new DTMF sequence should be looked for. */
2588         if (i != -1) {
2589                 return 0;
2590         }
2591
2592         if (conf_find_menu_entry_by_sequence(dtmf, menu, &new_menu_entry)) {
2593                 execute_menu_entry(conference,
2594                         user,
2595                         bridge_channel,
2596                         &new_menu_entry, menu);
2597                 conf_menu_entry_destroy(&new_menu_entry);
2598         }
2599         return 0;
2600 }
2601
2602 static int action_kick_last(struct confbridge_conference *conference,
2603         struct ast_bridge_channel *bridge_channel,
2604         struct confbridge_user *user)
2605 {
2606         struct confbridge_user *last_user = NULL;
2607         int isadmin = ast_test_flag(&user->u_profile, USER_OPT_ADMIN);
2608
2609         if (!isadmin) {
2610                 play_file(bridge_channel, NULL,
2611                         conf_get_sound(CONF_SOUND_ERROR_MENU, conference->b_profile.sounds));
2612                 ast_log(LOG_WARNING, "Only admin users can use the kick_last menu action. Channel %s of conf %s is not an admin.\n",
2613                         ast_channel_name(bridge_channel->chan),
2614                         conference->name);
2615                 return -1;
2616         }
2617
2618         ao2_lock(conference);
2619         if (((last_user = AST_LIST_LAST(&conference->active_list)) == user)
2620                 || (ast_test_flag(&last_user->u_profile, USER_OPT_ADMIN))) {
2621                 ao2_unlock(conference);
2622                 play_file(bridge_channel, NULL,
2623                         conf_get_sound(CONF_SOUND_ERROR_MENU, conference->b_profile.sounds));
2624         } else if (last_user && !last_user->kicked) {
2625                 last_user->kicked = 1;
2626                 pbx_builtin_setvar_helper(last_user->chan, "CONFBRIDGE_RESULT", "KICKED");
2627                 ast_bridge_remove(conference->bridge, last_user->chan);
2628                 ao2_unlock(conference);
2629         }
2630         return 0;
2631 }
2632
2633 static int action_dialplan_exec(struct ast_bridge_channel *bridge_channel, struct conf_menu_action *menu_action)
2634 {
2635         struct ast_pbx_args args;
2636         struct ast_pbx *pbx;
2637         char *exten;
2638         char *context;
2639         int priority;
2640         int res;
2641
2642         memset(&args, 0, sizeof(args));
2643         args.no_hangup_chan = 1;
2644
2645         ast_channel_lock(bridge_channel->chan);
2646
2647         /*save off*/
2648         exten = ast_strdupa(ast_channel_exten(bridge_channel->chan));
2649         context = ast_strdupa(ast_channel_context(bridge_channel->chan));
2650         priority = ast_channel_priority(bridge_channel->chan);
2651         pbx = ast_channel_pbx(bridge_channel->chan);
2652         ast_channel_pbx_set(bridge_channel->chan, NULL);
2653
2654         /*set new*/
2655         ast_channel_exten_set(bridge_channel->chan, menu_action->data.dialplan_args.exten);
2656         ast_channel_context_set(bridge_channel->chan, menu_action->data.dialplan_args.context);
2657         ast_channel_priority_set(bridge_channel->chan, menu_action->data.dialplan_args.priority);
2658
2659         ast_channel_unlock(bridge_channel->chan);
2660
2661         /*execute*/
2662         res = ast_pbx_run_args(bridge_channel->chan, &args);
2663
2664         /*restore*/
2665         ast_channel_lock(bridge_channel->chan);
2666
2667         ast_channel_exten_set(bridge_channel->chan, exten);
2668         ast_channel_context_set(bridge_channel->chan, context);
2669         ast_channel_priority_set(bridge_channel->chan, priority);
2670         ast_channel_pbx_set(bridge_channel->chan, pbx);
2671
2672         ast_channel_unlock(bridge_channel->chan);
2673
2674         return res;
2675 }
2676
2677 static int execute_menu_entry(struct confbridge_conference *conference,
2678         struct confbridge_user *user,
2679         struct ast_bridge_channel *bridge_channel,
2680         struct conf_menu_entry *menu_entry,
2681         struct conf_menu *menu)
2682 {
2683         struct conf_menu_action *menu_action;
2684         int isadmin = ast_test_flag(&user->u_profile, USER_OPT_ADMIN);
2685         int stop_prompts = 0;
2686         int res = 0;
2687
2688         AST_LIST_TRAVERSE(&menu_entry->actions, menu_action, action) {
2689                 switch (menu_action->id) {
2690                 case MENU_ACTION_TOGGLE_MUTE:
2691                         res |= action_toggle_mute(conference, user, bridge_channel);
2692                         break;
2693                 case MENU_ACTION_TOGGLE_BINAURAL:
2694                         action_toggle_binaural(conference, user, bridge_channel);
2695                         break;
2696                 case MENU_ACTION_ADMIN_TOGGLE_MUTE_PARTICIPANTS:
2697                         if (!isadmin) {
2698                                 break;
2699                         }
2700                         action_toggle_mute_participants(conference, user);
2701                         break;
2702                 case MENU_ACTION_PARTICIPANT_COUNT:
2703                         announce_user_count(conference, user, bridge_channel);
2704                         break;
2705                 case MENU_ACTION_PLAYBACK:
2706                         if (!stop_prompts) {
2707                                 res |= action_playback(bridge_channel, menu_action->data.playback_file);
2708                                 ast_test_suite_event_notify("CONF_MENU_PLAYBACK",
2709                                         "Message: %s\r\nChannel: %s",
2710                                         menu_action->data.playback_file, ast_channel_name(bridge_channel->chan));
2711                         }
2712                         break;
2713                 case MENU_ACTION_RESET_LISTENING:
2714                         ast_audiohook_volume_set(user->chan, AST_AUDIOHOOK_DIRECTION_WRITE, 0);
2715                         break;
2716                 case MENU_ACTION_RESET_TALKING:
2717                         ast_audiohook_volume_set(user->chan, AST_AUDIOHOOK_DIRECTION_READ, 0);
2718                         break;
2719                 case MENU_ACTION_INCREASE_LISTENING:
2720                         ast_audiohook_volume_adjust(user->chan,
2721                                 AST_AUDIOHOOK_DIRECTION_WRITE, 1);
2722                         break;
2723                 case MENU_ACTION_DECREASE_LISTENING:
2724                         ast_audiohook_volume_adjust(user->chan,
2725                                 AST_AUDIOHOOK_DIRECTION_WRITE, -1);
2726                         break;
2727                 case MENU_ACTION_INCREASE_TALKING:
2728                         ast_audiohook_volume_adjust(user->chan,
2729                                 AST_AUDIOHOOK_DIRECTION_READ, 1);
2730                         break;
2731                 case MENU_ACTION_DECREASE_TALKING:
2732                         ast_audiohook_volume_adjust(user->chan,
2733                                 AST_AUDIOHOOK_DIRECTION_READ, -1);
2734                         break;
2735                 case MENU_ACTION_PLAYBACK_AND_CONTINUE:
2736                         if (!(stop_prompts)) {
2737                                 res |= action_playback_and_continue(conference,
2738                                         user,
2739                                         bridge_channel,
2740                                         menu,
2741                                         menu_action->data.playback_file,
2742                                         menu_entry->dtmf,
2743                                         &stop_prompts);
2744                         }
2745                         break;
2746                 case MENU_ACTION_DIALPLAN_EXEC:
2747                         res |= action_dialplan_exec(bridge_channel, menu_action);
2748                         break;
2749                 case MENU_ACTION_ADMIN_TOGGLE_LOCK:
2750                         if (!isadmin) {
2751                                 break;
2752                         }
2753                         conference->locked = (!conference->locked ? 1 : 0);
2754                         res |= play_file(bridge_channel, NULL,
2755                                 conf_get_sound(
2756                                         conference->locked ? CONF_SOUND_LOCKED_NOW : CONF_SOUND_UNLOCKED_NOW,
2757                                         conference->b_profile.sounds)) < 0;
2758                         break;
2759                 case MENU_ACTION_ADMIN_KICK_LAST:
2760                         res |= action_kick_last(conference, bridge_channel, user);
2761                         break;
2762                 case MENU_ACTION_LEAVE:
2763                         pbx_builtin_setvar_helper(bridge_channel->chan, "CONFBRIDGE_RESULT", "DTMF");
2764                         ao2_lock(conference);
2765                         ast_bridge_remove(conference->bridge, bridge_channel->chan);
2766                         ast_test_suite_event_notify("CONF_MENU_LEAVE",
2767                                 "Channel: %s",
2768                                 ast_channel_name(bridge_channel->chan));
2769                         ao2_unlock(conference);
2770                         break;
2771                 case MENU_ACTION_NOOP:
2772                         break;
2773                 case MENU_ACTION_SET_SINGLE_VIDEO_SRC:
2774                         ao2_lock(conference);
2775                         if (!ast_test_flag(&conference->b_profile, BRIDGE_OPT_VIDEO_SRC_SFU)) {
2776                                 ast_bridge_set_single_src_video_mode(conference->bridge, bridge_channel->chan);
2777                         }
2778                         ao2_unlock(conference);
2779                         break;
2780                 case MENU_ACTION_RELEASE_SINGLE_VIDEO_SRC:
2781                         handle_video_on_exit(conference, bridge_channel->chan);
2782                         break;
2783                 }
2784         }
2785         return res;
2786 }
2787
2788 int conf_handle_dtmf(struct ast_bridge_channel *bridge_channel,
2789         struct confbridge_user *user,
2790         struct conf_menu_entry *menu_entry,
2791         struct conf_menu *menu)
2792 {
2793         /* See if music on hold is playing */
2794         conf_moh_suspend(user);
2795
2796         /* execute the list of actions associated with this menu entry */
2797         execute_menu_entry(user->conference, user, bridge_channel, menu_entry, menu);
2798
2799         /* See if music on hold needs to be started back up again */
2800         conf_moh_unsuspend(user);
2801
2802         async_play_sound_ready(bridge_channel->chan);
2803
2804         return 0;
2805 }
2806
2807 static int kick_conference_participant(struct confbridge_conference *conference,
2808         const char *channel)
2809 {
2810         int res = -1;
2811         int match;
2812         struct confbridge_user *user = NULL;
2813         int all = !strcasecmp("all", channel);
2814         int participants = !strcasecmp("participants", channel);
2815
2816         SCOPED_AO2LOCK(bridge_lock, conference);
2817
2818         AST_LIST_TRAVERSE(&conference->active_list, user, list) {
2819                 if (user->kicked) {
2820                         continue;
2821                 }
2822                 match = !strcasecmp(channel, ast_channel_name(user->chan));
2823                 if (match || all
2824                                 || (participants && !ast_test_flag(&user->u_profile, USER_OPT_ADMIN))) {
2825                         user->kicked = 1;
2826                         pbx_builtin_setvar_helper(user->chan, "CONFBRIDGE_RESULT", "KICKED");
2827                         ast_bridge_remove(conference->bridge, user->chan);
2828                         res = 0;
2829                         if (match) {
2830                                 return res;
2831                         }
2832                 }
2833         }
2834         AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
2835                 if (user->kicked) {
2836                         continue;
2837                 }
2838                 match = !strcasecmp(channel, ast_channel_name(user->chan));
2839                 if (match || all
2840                                 || (participants && !ast_test_flag(&user->u_profile, USER_OPT_ADMIN))) {
2841                         user->kicked = 1;
2842                         pbx_builtin_setvar_helper(user->chan, "CONFBRIDGE_RESULT", "KICKED");
2843                         ast_bridge_remove(conference->bridge, user->chan);
2844                         res = 0;
2845                         if (match) {
2846                                 return res;
2847                         }
2848                 }
2849         }
2850
2851         return res;
2852 }
2853
2854 static char *complete_confbridge_name(const char *line, const char *word, int pos, int state)
2855 {
2856         int which = 0;
2857         struct confbridge_conference *conference;
2858         char *res = NULL;
2859         int wordlen = strlen(word);
2860         struct ao2_iterator iter;
2861
2862         iter = ao2_iterator_init(conference_bridges, 0);
2863         while ((conference = ao2_iterator_next(&iter))) {
2864                 if (!strncasecmp(conference->name, word, wordlen) && ++which > state) {
2865                         res = ast_strdup(conference->name);
2866                         ao2_ref(conference, -1);
2867                         break;
2868                 }
2869                 ao2_ref(conference, -1);
2870         }
2871         ao2_iterator_destroy(&iter);
2872
2873         return res;
2874 }
2875
2876 static char *complete_confbridge_participant(const char *conference_name, const char *line, const char *word, int pos, int state)
2877 {
2878         int which = 0;
2879         RAII_VAR(struct confbridge_conference *, conference, NULL, ao2_cleanup);
2880         struct confbridge_user *user;
2881         char *res = NULL;
2882         int wordlen = strlen(word);
2883
2884         conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
2885         if (!conference) {
2886                 return NULL;
2887         }
2888
2889         if (!strncasecmp("all", word, wordlen) && ++which > state) {
2890                 return ast_strdup("all");
2891         }
2892
2893         if (!strncasecmp("participants", word, wordlen) && ++which > state) {
2894                 return ast_strdup("participants");
2895         }
2896
2897         {
2898                 SCOPED_AO2LOCK(bridge_lock, conference);
2899                 AST_LIST_TRAVERSE(&conference->active_list, user, list) {
2900                         if (!strncasecmp(ast_channel_name(user->chan), word, wordlen) && ++which > state) {
2901                                 res = ast_strdup(ast_channel_name(user->chan));
2902                                 return res;
2903                         }
2904                 }
2905                 AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
2906                         if (!strncasecmp(ast_channel_name(user->chan), word, wordlen) && ++which > state) {
2907                                 res = ast_strdup(ast_channel_name(user->chan));
2908                                 return res;
2909                         }
2910                 }
2911         }
2912
2913         return NULL;
2914 }
2915
2916 static char *handle_cli_confbridge_kick(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2917 {
2918         struct confbridge_conference *conference;
2919         int not_found;
2920
2921         switch (cmd) {
2922         case CLI_INIT:
2923                 e->command = "confbridge kick";
2924                 e->usage =
2925                         "Usage: confbridge kick <conference> <channel>\n"
2926                         "       Kicks a channel out of the conference bridge.\n"
2927                         "             (all to kick everyone, participants to kick non-admins).\n";
2928                 return NULL;
2929         case CLI_GENERATE:
2930                 if (a->pos == 2) {
2931                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
2932                 }
2933                 if (a->pos == 3) {
2934                         return complete_confbridge_participant(a->argv[2], a->line, a->word, a->pos, a->n);
2935                 }
2936                 return NULL;
2937         }
2938
2939         if (a->argc != 4) {
2940                 return CLI_SHOWUSAGE;
2941         }
2942
2943         conference = ao2_find(conference_bridges, a->argv[2], OBJ_KEY);
2944         if (!conference) {
2945                 ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
2946                 return CLI_SUCCESS;
2947         }
2948         not_found = kick_conference_participant(conference, a->argv[3]);
2949         ao2_ref(conference, -1);
2950         if (not_found) {
2951                 if (!strcasecmp("all", a->argv[3]) || !strcasecmp("participants", a->argv[3])) {
2952                         ast_cli(a->fd, "No participants found!\n");
2953                 } else {
2954                         ast_cli(a->fd, "No participant named '%s' found!\n", a->argv[3]);
2955                 }
2956                 return CLI_SUCCESS;
2957         }
2958         ast_cli(a->fd, "Kicked '%s' out of conference '%s'\n", a->argv[3], a->argv[2]);
2959         return CLI_SUCCESS;
2960 }
2961
2962 static void handle_cli_confbridge_list_item(struct ast_cli_args *a, struct confbridge_user *user, int waiting)
2963 {
2964         char flag_str[6 + 1];/* Max flags + terminator */
2965         int pos = 0;
2966
2967         /* Build flags column string. */
2968         if (ast_test_flag(&user->u_profile, USER_OPT_ADMIN)) {
2969                 flag_str[pos++] = 'A';
2970         }
2971         if (ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER)) {
2972                 flag_str[pos++] = 'M';
2973         }
2974         if (ast_test_flag(&user->u_profile, USER_OPT_WAITMARKED)) {
2975                 flag_str[pos++] = 'W';
2976         }
2977         if (ast_test_flag(&user->u_profile, USER_OPT_ENDMARKED)) {
2978                 flag_str[pos++] = 'E';
2979         }
2980         if (user->muted) {
2981                 flag_str[pos++] = 'm';
2982         }
2983         if (waiting) {
2984                 flag_str[pos++] = 'w';
2985         }
2986         flag_str[pos] = '\0';
2987
2988         ast_cli(a->fd, "%-30s %-6s %-16s %-16s %-16s %s\n",
2989                 ast_channel_name(user->chan),
2990                 flag_str,
2991                 user->u_profile.name,
2992                 user->conference->b_profile.name,
2993                 user->menu_name,
2994                 S_COR(ast_channel_caller(user->chan)->id.number.valid,
2995                         ast_channel_caller(user->chan)->id.number.str, "<unknown>"));
2996 }
2997
2998 static char *handle_cli_confbridge_list(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2999 {
3000         struct confbridge_conference *conference;
3001
3002         switch (cmd) {
3003         case CLI_INIT:
3004                 e->command = "confbridge list";
3005                 e->usage =
3006                         "Usage: confbridge list [<name>]\n"
3007                         "       Lists all currently active conference bridges or a specific conference bridge.\n"
3008                         "\n"
3009                         "       When a conference bridge name is provided, flags may be shown for users. Below\n"
3010                         "       are the flags and what they represent.\n"
3011                         "\n"
3012                         "       Flags:\n"
3013                         "         A - The user is an admin\n"
3014                         "         M - The user is a marked user\n"
3015                         "         W - The user must wait for a marked user to join\n"
3016                         "         E - The user will be kicked after the last marked user leaves the conference\n"
3017                         "         m - The user is muted\n"
3018                         "         w - The user is waiting for a marked user to join\n";
3019                 return NULL;
3020         case CLI_GENERATE:
3021                 if (a->pos == 2) {
3022                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
3023                 }
3024                 return NULL;
3025         }
3026
3027         if (a->argc == 2) {
3028                 struct ao2_iterator iter;
3029
3030                 ast_cli(a->fd, "Conference Bridge Name           Users  Marked Locked Muted\n");
3031                 ast_cli(a->fd, "================================ ====== ====== ====== =====\n");
3032                 iter = ao2_iterator_init(conference_bridges, 0);
3033                 while ((conference = ao2_iterator_next(&iter))) {
3034                         ast_cli(a->fd, "%-32s %6u %6u %-6s %s\n",
3035                                 conference->name,
3036                                 conference->activeusers + conference->waitingusers,
3037                                 conference->markedusers,
3038                                 AST_CLI_YESNO(conference->locked),
3039                                 AST_CLI_YESNO(conference->muted));
3040                         ao2_ref(conference, -1);
3041                 }
3042                 ao2_iterator_destroy(&iter);
3043                 return CLI_SUCCESS;
3044         }
3045
3046         if (a->argc == 3) {
3047                 struct confbridge_user *user;
3048
3049                 conference = ao2_find(conference_bridges, a->argv[2], OBJ_KEY);
3050                 if (!conference) {
3051                         ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
3052                         return CLI_SUCCESS;
3053                 }
3054                 ast_cli(a->fd, "Channel                        Flags  User Profile     Bridge Profile   Menu             CallerID\n");
3055                 ast_cli(a->fd, "============================== ====== ================ ================ ================ ================\n");
3056                 ao2_lock(conference);
3057                 AST_LIST_TRAVERSE(&conference->active_list, user, list) {
3058                         handle_cli_confbridge_list_item(a, user, 0);
3059                 }
3060                 AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
3061                         handle_cli_confbridge_list_item(a, user, 1);
3062                 }
3063                 ao2_unlock(conference);
3064                 ao2_ref(conference, -1);
3065                 return CLI_SUCCESS;
3066         }
3067
3068         return CLI_SHOWUSAGE;
3069 }
3070
3071 /* \internal
3072  * \brief finds a conference by name and locks/unlocks.
3073  *
3074  * \retval 0 success
3075  * \retval -1 conference not found
3076  */
3077 static int generic_lock_unlock_helper(int lock, const char *conference_name)
3078 {
3079         struct confbridge_conference *conference;
3080         int res = 0;
3081
3082         conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
3083         if (!conference) {
3084                 return -1;
3085         }
3086         ao2_lock(conference);
3087         conference->locked = lock;
3088         ast_test_suite_event_notify("CONF_LOCK", "Message: conference %s\r\nConference: %s", conference->locked ? "locked" : "unlocked", conference->b_profile.name);
3089         ao2_unlock(conference);
3090         ao2_ref(conference, -1);
3091
3092         return res;
3093 }
3094
3095 /* \internal
3096  * \brief finds a conference user by channel name and mutes/unmutes them.
3097  *
3098  * \retval 0 success
3099  * \retval -1 conference not found
3100  * \retval -2 user not found
3101  */
3102 static int generic_mute_unmute_helper(int mute, const char *conference_name,
3103         const char *chan_name)
3104 {
3105         RAII_VAR(struct confbridge_conference *, conference, NULL, ao2_cleanup);
3106         struct confbridge_user *user;
3107         int all = !strcasecmp("all", chan_name);
3108         int participants = !strcasecmp("participants", chan_name);
3109         int res = -2;
3110
3111         conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
3112         if (!conference) {
3113                 return -1;
3114         }
3115
3116         {
3117                 SCOPED_AO2LOCK(bridge_lock, conference);
3118                 AST_LIST_TRAVERSE(&conference->active_list, user, list) {
3119                         int match = !strncasecmp(chan_name, ast_channel_name(user->chan),
3120                                 strlen(chan_name));
3121                         if (match || all
3122                                 || (participants && !ast_test_flag(&user->u_profile, USER_OPT_ADMIN))) {
3123                                 generic_mute_unmute_user(conference, user, mute);
3124                                 res = 0;
3125                                 if (match) {
3126                                         return res;
3127                                 }
3128                         }
3129                 }
3130
3131                 AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
3132                         int match = !strncasecmp(chan_name, ast_channel_name(user->chan),
3133                                 strlen(chan_name));
3134                         if (match || all
3135                                 || (participants && !ast_test_flag(&user->u_profile, USER_OPT_ADMIN))) {
3136                                 generic_mute_unmute_user(conference, user, mute);
3137                                 res = 0;
3138                                 if (match) {
3139                                         return res;
3140                                 }
3141                         }
3142                 }
3143         }
3144
3145         return res;
3146 }
3147
3148 static int cli_mute_unmute_helper(int mute, struct ast_cli_args *a)
3149 {
3150         int res = generic_mute_unmute_helper(mute, a->argv[2], a->argv[3]);
3151
3152         if (res == -1) {
3153                 ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
3154                 return -1;
3155         } else if (res == -2) {
3156                 if (!strcasecmp("all", a->argv[3]) || !strcasecmp("participants", a->argv[3])) {
3157                         ast_cli(a->fd, "No participants found in conference %s\n", a->argv[2]);
3158                 } else {
3159                         ast_cli(a->fd, "No channel named '%s' found in conference %s\n", a->argv[3], a->argv[2]);
3160                 }
3161                 return -1;
3162         }
3163         ast_cli(a->fd, "%s %s from confbridge %s\n", mute ? "Muting" : "Unmuting", a->argv[3], a->argv[2]);
3164         return 0;
3165 }
3166
3167 static char *handle_cli_confbridge_mute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3168 {
3169         switch (cmd) {
3170         case CLI_INIT:
3171                 e->command = "confbridge mute";
3172                 e->usage =
3173                         "Usage: confbridge mute <conference> <channel>\n"
3174                         "       Mute a channel in a conference.\n"
3175                         "              (all to mute everyone, participants to mute non-admins)\n"
3176                         "       If the specified channel is a prefix,\n"
3177                         "       the action will be taken on the first\n"
3178                         "       matching channel.\n";
3179                 return NULL;
3180         case CLI_GENERATE:
3181                 if (a->pos == 2) {
3182                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
3183                 }
3184                 if (a->pos == 3) {
3185                         return complete_confbridge_participant(a->argv[2], a->line, a->word, a->pos, a->n);
3186                 }
3187                 return NULL;
3188         }
3189         if (a->argc != 4) {
3190                 return CLI_SHOWUSAGE;
3191         }
3192
3193         cli_mute_unmute_helper(1, a);
3194
3195         return CLI_SUCCESS;
3196 }
3197
3198 static char *handle_cli_confbridge_unmute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3199 {
3200         switch (cmd) {
3201         case CLI_INIT:
3202                 e->command = "confbridge unmute";
3203                 e->usage =
3204                         "Usage: confbridge unmute <conference> <channel>\n"
3205                         "       Unmute a channel in a conference.\n"
3206                         "              (all to unmute everyone, participants to unmute non-admins)\n"
3207                         "       If the specified channel is a prefix,\n"
3208                         "       the action will be taken on the first\n"
3209                         "       matching channel.\n";
3210                 return NULL;
3211         case CLI_GENERATE:
3212                 if (a->pos == 2) {
3213                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
3214                 }
3215                 if (a->pos == 3) {
3216                         return complete_confbridge_participant(a->argv[2], a->line, a->word, a->pos, a->n);
3217                 }
3218                 return NULL;
3219         }
3220         if (a->argc != 4) {
3221                 return CLI_SHOWUSAGE;
3222         }
3223
3224         cli_mute_unmute_helper(0, a);
3225
3226         return CLI_SUCCESS;
3227 }
3228
3229 static char *handle_cli_confbridge_lock(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3230 {
3231         switch (cmd) {
3232         case CLI_INIT:
3233                 e->command = "confbridge lock";
3234                 e->usage =
3235                         "Usage: confbridge lock <conference>\n"
3236                         "       Lock a conference. While locked, no new non-admins\n"
3237                         "       may join the conference.\n";
3238                 return NULL;
3239         case CLI_GENERATE:
3240                 if (a->pos == 2) {
3241                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
3242                 }
3243                 return NULL;
3244         }
3245         if (a->argc != 3) {
3246                 return CLI_SHOWUSAGE;
3247         }
3248         if (generic_lock_unlock_helper(1, a->argv[2])) {
3249                 ast_cli(a->fd, "Conference %s is not found\n", a->argv[2]);
3250         } else {
3251                 ast_cli(a->fd, "Conference %s is locked.\n", a->argv[2]);
3252         }
3253         return CLI_SUCCESS;
3254 }
3255
3256 static char *handle_cli_confbridge_unlock(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3257 {
3258         switch (cmd) {
3259         case CLI_INIT:
3260                 e->command = "confbridge unlock";
3261                 e->usage =
3262                         "Usage: confbridge unlock <conference>\n"
3263                         "       Unlock a previously locked conference.\n";
3264                 return NULL;
3265         case CLI_GENERATE:
3266                 if (a->pos == 2) {
3267                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
3268                 }
3269                 return NULL;
3270         }
3271         if (a->argc != 3) {
3272                 return CLI_SHOWUSAGE;
3273         }
3274         if (generic_lock_unlock_helper(0, a->argv[2])) {
3275                 ast_cli(a->fd, "Conference %s is not found\n", a->argv[2]);
3276         } else {
3277                 ast_cli(a->fd, "Conference %s is unlocked.\n", a->argv[2]);
3278         }
3279         return CLI_SUCCESS;
3280 }
3281
3282 static char *handle_cli_confbridge_start_record(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3283 {
3284         const char *rec_file = NULL;
3285         struct confbridge_conference *conference;
3286
3287         switch (cmd) {
3288         case CLI_INIT:
3289                 e->command = "confbridge record start";
3290                 e->usage =
3291                         "Usage: confbridge record start <conference> <file>\n"
3292                         "       <file> is optional, Otherwise the bridge profile\n"
3293                         "       record file will be used.  If the bridge profile\n"
3294                         "       has no record file specified, a file will automatically\n"
3295                         "       be generated in the monitor directory\n";
3296                 return NULL;
3297         case CLI_GENERATE:
3298                 if (a->pos == 3) {
3299                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
3300                 }
3301                 return NULL;
3302         }
3303         if (a->argc < 4) {
3304                 return CLI_SHOWUSAGE;
3305         }
3306         if (a->argc == 5) {
3307                 rec_file = a->argv[4];
3308         }
3309
3310         conference = ao2_find(conference_bridges, a->argv[3], OBJ_KEY);
3311         if (!conference) {
3312                 ast_cli(a->fd, "Conference not found.\n");
3313                 return CLI_FAILURE;
3314         }
3315         ao2_lock(conference);
3316         if (conf_is_recording(conference)) {
3317                 ast_cli(a->fd, "Conference is already being recorded.\n");
3318                 ao2_unlock(conference);
3319                 ao2_ref(conference, -1);
3320                 return CLI_SUCCESS;
3321         }
3322         if (!ast_strlen_zero(rec_file)) {
3323                 ast_copy_string(conference->b_profile.rec_file, rec_file, sizeof(conference->b_profile.rec_file));
3324         }
3325
3326         if (conf_start_record(conference)) {
3327                 ast_cli(a->fd, "Could not start recording due to internal error.\n");
3328                 ao2_unlock(conference);
3329                 ao2_ref(conference, -1);
3330                 return CLI_FAILURE;
3331         }
3332         ao2_unlock(conference);
3333
3334         ast_cli(a->fd, "Recording started\n");
3335         ao2_ref(conference, -1);
3336         return CLI_SUCCESS;
3337 }
3338
3339 static char *handle_cli_confbridge_stop_record(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3340 {
3341         struct confbridge_conference *conference;
3342         int ret;
3343
3344         switch (cmd) {
3345         case CLI_INIT:
3346                 e->command = "confbridge record stop";
3347                 e->usage =
3348                         "Usage: confbridge record stop <conference>\n"
3349                         "       Stop a previously started recording.\n";
3350                 return NULL;
3351         case CLI_GENERATE:
3352                 if (a->pos == 3) {
3353                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
3354                 }
3355                 return NULL;
3356         }
3357         if (a->argc != 4) {
3358                 return CLI_SHOWUSAGE;
3359         }
3360
3361         conference = ao2_find(conference_bridges, a->argv[3], OBJ_KEY);
3362         if (!conference) {
3363                 ast_cli(a->fd, "Conference not found.\n");
3364                 return CLI_SUCCESS;
3365         }
3366         ao2_lock(conference);
3367         ret = conf_stop_record(conference);
3368         ao2_unlock(conference);
3369         ast_cli(a->fd, "Recording %sstopped.\n", ret ? "could not be " : "");
3370         ao2_ref(conference, -1);
3371         return CLI_SUCCESS;
3372 }
3373
3374 static struct ast_cli_entry cli_confbridge[] = {
3375         AST_CLI_DEFINE(handle_cli_confbridge_list, "List conference bridges and participants."),
3376         AST_CLI_DEFINE(handle_cli_confbridge_kick, "Kick participants out of conference bridges."),
3377         AST_CLI_DEFINE(handle_cli_confbridge_mute, "Mute participants."),
3378         AST_CLI_DEFINE(handle_cli_confbridge_unmute, "Unmute participants."),
3379         AST_CLI_DEFINE(handle_cli_confbridge_lock, "Lock a conference."),
3380         AST_CLI_DEFINE(handle_cli_confbridge_unlock, "Unlock a conference."),
3381         AST_CLI_DEFINE(handle_cli_confbridge_start_record, "Start recording a conference"),
3382         AST_CLI_DEFINE(handle_cli_confbridge_stop_record, "Stop recording a conference."),
3383 };
3384 static struct ast_custom_function confbridge_function = {
3385         .name = "CONFBRIDGE",
3386         .write = func_confbridge_helper,
3387 };
3388
3389 static int func_confbridge_info(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len);
3390 static struct ast_custom_function confbridge_info_function = {
3391         .name = "CONFBRIDGE_INFO",
3392         .read = func_confbridge_info,
3393 };
3394
3395 static void action_confbridgelist_item(struct mansession *s, const char *id_text, struct confbridge_conference *conference, struct confbridge_user *user, int waiting)
3396 {
3397         astman_append(s,
3398                 "Event: ConfbridgeList\r\n"
3399                 "%s"
3400                 "Conference: %s\r\n"
3401                 "CallerIDNum: %s\r\n"
3402                 "CallerIDName: %s\r\n"
3403                 "Channel: %s\r\n"
3404                 "Admin: %s\r\n"
3405                 "MarkedUser: %s\r\n"
3406                 "WaitMarked: %s\r\n"
3407                 "EndMarked: %s\r\n"
3408                 "Waiting: %s\r\n"
3409                 "Muted: %s\r\n"
3410                 "AnsweredTime: %d\r\n"
3411                 "\r\n",
3412                 id_text,
3413                 conference->name,
3414                 S_COR(ast_channel_caller(user->chan)->id.number.valid, ast_channel_caller(user->chan)->id.number.str, "<unknown>"),
3415                 S_COR(ast_channel_caller(user->chan)->id.name.valid, ast_channel_caller(user->chan)->id.name.str, "<no name>"),
3416                 ast_channel_name(user->chan),
3417                 ast_test_flag(&user->u_profile, USER_OPT_ADMIN) ? "Yes" : "No",
3418                 ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER) ? "Yes" : "No",
3419                 ast_test_flag(&user->u_profile, USER_OPT_WAITMARKED) ? "Yes" : "No",
3420                 ast_test_flag(&user->u_profile, USER_OPT_ENDMARKED) ? "Yes" : "No",
3421                 waiting ? "Yes" : "No",
3422                 user->muted ? "Yes" : "No",
3423                 ast_channel_get_up_time(user->chan));
3424 }
3425
3426 static int action_confbridgelist(struct mansession *s, const struct message *m)
3427 {
3428         const char *actionid = astman_get_header(m, "ActionID");
3429         const char *conference_name = astman_get_header(m, "Conference");
3430         struct confbridge_user *user;
3431         struct confbridge_conference *conference;
3432         char id_text[80];
3433         int total = 0;
3434
3435         id_text[0] = '\0';
3436         if (!ast_strlen_zero(actionid)) {
3437                 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", actionid);
3438         }
3439         if (ast_strlen_zero(conference_name)) {
3440                 astman_send_error(s, m, "No Conference name provided.");
3441                 return 0;
3442         }
3443         if (!ao2_container_count(conference_bridges)) {
3444                 astman_send_error(s, m, "No active conferences.");
3445                 return 0;
3446         }
3447         conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
3448         if (!conference) {
3449                 astman_send_error(s, m, "No Conference by that name found.");
3450                 return 0;
3451         }
3452
3453         astman_send_listack(s, m, "Confbridge user list will follow", "start");
3454
3455         ao2_lock(conference);
3456         AST_LIST_TRAVERSE(&conference->active_list, user, list) {
3457                 total++;
3458                 action_confbridgelist_item(s, id_text, conference, user, 0);
3459         }
3460         AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
3461                 total++;
3462                 action_confbridgelist_item(s, id_text, conference, user, 1);
3463         }
3464         ao2_unlock(conference);
3465         ao2_ref(conference, -1);
3466
3467         astman_send_list_complete_start(s, m, "ConfbridgeListComplete", total);
3468         astman_send_list_complete_end(s);
3469
3470         return 0;
3471 }
3472
3473 static int action_confbridgelistrooms(struct mansession *s, const struct message *m)
3474 {
3475         const char *actionid = astman_get_header(m, "ActionID");
3476         struct confbridge_conference *conference;
3477         struct ao2_iterator iter;
3478         char id_text[512] = "";
3479         int totalitems = 0;
3480
3481         if (!ast_strlen_zero(actionid)) {
3482                 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", actionid);
3483         }
3484
3485         if (!ao2_container_count(conference_bridges)) {
3486                 astman_send_error(s, m, "No active conferences.");
3487                 return 0;
3488         }
3489
3490         astman_send_listack(s, m, "Confbridge conferences will follow", "start");
3491
3492         /* Traverse the conference list */
3493         iter = ao2_iterator_init(conference_bridges, 0);
3494         while ((conference = ao2_iterator_next(&iter))) {
3495                 totalitems++;
3496
3497                 ao2_lock(conference);
3498                 astman_append(s,
3499                 "Event: ConfbridgeListRooms\r\n"
3500                 "%s"
3501                 "Conference: %s\r\n"
3502                 "Parties: %u\r\n"
3503                 "Marked: %u\r\n"
3504                 "Locked: %s\r\n"
3505                 "Muted: %s\r\n"
3506                 "\r\n",
3507                 id_text,
3508                 conference->name,
3509                 conference->activeusers + conference->waitingusers,
3510                 conference->markedusers,
3511                 AST_YESNO(conference->locked),
3512                 AST_YESNO(conference->muted));
3513                 ao2_unlock(conference);
3514
3515                 ao2_ref(conference, -1);
3516         }
3517         ao2_iterator_destroy(&iter);
3518
3519         /* Send final confirmation */
3520         astman_send_list_complete_start(s, m, "ConfbridgeListRoomsComplete", totalitems);
3521         astman_send_list_complete_end(s);
3522         return 0;
3523 }
3524
3525 static int action_mute_unmute_helper(struct mansession *s, const struct message *m, int mute)
3526 {
3527         const char *conference_name = astman_get_header(m, "Conference");
3528         const char *channel_name = astman_get_header(m, "Channel");
3529         int res = 0;
3530
3531         if (ast_strlen_zero(conference_name)) {
3532                 astman_send_error(s, m, "No Conference name provided.");
3533                 return 0;
3534         }
3535         if (ast_strlen_zero(channel_name)) {
3536                 astman_send_error(s, m, "No channel name provided.");
3537                 return 0;
3538         }
3539         if (!ao2_container_count(conference_bridges)) {
3540                 astman_send_error(s, m, "No active conferences.");
3541                 return 0;
3542         }
3543
3544         res = generic_mute_unmute_helper(mute, conference_name, channel_name);
3545
3546         if (res == -1) {
3547                 astman_send_error(s, m, "No Conference by that name found.");
3548                 return 0;
3549         } else if (res == -2) {
3550                 astman_send_error(s, m, "No Channel by that name found in Conference.");
3551                 return 0;
3552         }
3553
3554         astman_send_ack(s, m, mute ? "User muted" : "User unmuted");
3555         return 0;
3556 }
3557
3558 static int action_confbridgeunmute(struct mansession *s, const struct message *m)
3559 {
3560         return action_mute_unmute_helper(s, m, 0);
3561 }
3562 static int action_confbridgemute(struct mansession *s, const struct message *m)
3563 {
3564         return action_mute_unmute_helper(s, m, 1);
3565 }
3566
3567 static int action_lock_unlock_helper(struct mansession *s, const struct message *m, int lock)
3568 {
3569         const char *conference_name = astman_get_header(m, "Conference");
3570         int res = 0;
3571
3572         if (ast_strlen_zero(conference_name)) {
3573                 astman_send_error(s, m, "No Conference name provided.");
3574                 return 0;
3575         }
3576         if (!ao2_container_count(conference_bridges)) {
3577                 astman_send_error(s, m, "No active conferences.");
3578                 return 0;
3579         }
3580         if ((res = generic_lock_unlock_helper(lock, conference_name))) {
3581                 astman_send_error(s, m, "No Conference by that name found.");
3582                 return 0;
3583         }
3584         astman_send_ack(s, m, lock ? "Conference locked" : "Conference unlocked");
3585         return 0;
3586 }
3587 static int action_confbridgeunlock(struct mansession *s, const struct message *m)
3588 {
3589         return action_lock_unlock_helper(s, m, 0);
3590 }
3591 static int action_confbridgelock(struct mansession *s, const struct message *m)
3592 {
3593         return action_lock_unlock_helper(s, m, 1);
3594 }
3595
3596 static int action_confbridgekick(struct mansession *s, const struct message *m)
3597 {
3598         const char *conference_name = astman_get_header(m, "Conference");
3599         const char *channel = astman_get_header(m, "Channel");
3600         struct confbridge_conference *conference;
3601         int found;
3602
3603         if (ast_strlen_zero(conference_name)) {
3604                 astman_send_error(s, m, "No Conference name provided.");
3605                 return 0;
3606         }
3607         if (!ao2_container_count(conference_bridges)) {
3608                 astman_send_error(s, m, "No active conferences.");
3609                 return 0;
3610         }
3611
3612         conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
3613         if (!conference) {
3614                 astman_send_error(s, m, "No Conference by that name found.");
3615                 return 0;
3616         }
3617
3618         found = !kick_conference_participant(conference, channel);
3619         ao2_ref(conference, -1);
3620
3621         if (found) {
3622                 astman_send_ack(s, m, !strcmp("all", channel) ? "All participants kicked" : "User kicked");
3623         } else {
3624                 astman_send_error(s, m, "No Channel by that name found in Conference.");
3625         }
3626         return 0;
3627 }