Binaural synthesis (confbridge): Adds binaural synthesis to bridge_softmix.
[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_ONLY_ONE:
442                 return S_OR(custom_sounds->onlyone, "conf-onlyone");
443         case CONF_SOUND_THERE_ARE:
444                 return S_OR(custom_sounds->thereare, "conf-thereare");
445         case CONF_SOUND_OTHER_IN_PARTY:
446                 return S_OR(custom_sounds->otherinparty, "conf-otherinparty");
447         case CONF_SOUND_PLACE_IN_CONF:
448                 return S_OR(custom_sounds->placeintoconf, "conf-placeintoconf");
449         case CONF_SOUND_WAIT_FOR_LEADER:
450                 return S_OR(custom_sounds->waitforleader, "conf-waitforleader");
451         case CONF_SOUND_LEADER_HAS_LEFT:
452                 return S_OR(custom_sounds->leaderhasleft, "conf-leaderhasleft");
453         case CONF_SOUND_GET_PIN:
454                 return S_OR(custom_sounds->getpin, "conf-getpin");
455         case CONF_SOUND_INVALID_PIN:
456                 return S_OR(custom_sounds->invalidpin, "conf-invalidpin");
457         case CONF_SOUND_ONLY_PERSON:
458                 return S_OR(custom_sounds->onlyperson, "conf-onlyperson");
459         case CONF_SOUND_LOCKED:
460                 return S_OR(custom_sounds->locked, "conf-locked");
461         case CONF_SOUND_LOCKED_NOW:
462                 return S_OR(custom_sounds->lockednow, "conf-lockednow");
463         case CONF_SOUND_UNLOCKED_NOW:
464                 return S_OR(custom_sounds->unlockednow, "conf-unlockednow");
465         case CONF_SOUND_ERROR_MENU:
466                 return S_OR(custom_sounds->errormenu, "conf-errormenu");
467         case CONF_SOUND_JOIN:
468                 return S_OR(custom_sounds->join, "confbridge-join");
469         case CONF_SOUND_LEAVE:
470                 return S_OR(custom_sounds->leave, "confbridge-leave");
471         case CONF_SOUND_PARTICIPANTS_MUTED:
472                 return S_OR(custom_sounds->participantsmuted, "conf-now-muted");
473         case CONF_SOUND_PARTICIPANTS_UNMUTED:
474                 return S_OR(custom_sounds->participantsunmuted, "conf-now-unmuted");
475         case CONF_SOUND_BEGIN:
476                 return S_OR(custom_sounds->begin, "confbridge-conf-begin");
477         }
478
479         return "";
480 }
481
482 static void send_conf_stasis(struct confbridge_conference *conference, struct ast_channel *chan,
483         struct stasis_message_type *type, struct ast_json *extras, int channel_topic)
484 {
485         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
486         RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
487
488         json_object = ast_json_pack("{s: s}",
489                 "conference", conference->name);
490         if (!json_object) {
491                 return;
492         }
493
494         if (extras) {
495                 ast_json_object_update(json_object, extras);
496         }
497
498         ast_bridge_lock(conference->bridge);
499         msg = ast_bridge_blob_create(type,
500                 conference->bridge,
501                 chan,
502                 json_object);
503         ast_bridge_unlock(conference->bridge);
504         if (!msg) {
505                 return;
506         }
507
508         if (channel_topic) {
509                 stasis_publish(ast_channel_topic(chan), msg);
510         } else {
511                 stasis_publish(ast_bridge_topic(conference->bridge), msg);
512         }
513 }
514
515 static void send_conf_start_event(struct confbridge_conference *conference)
516 {
517         send_conf_stasis(conference, NULL, confbridge_start_type(), NULL, 0);
518 }
519
520 static void send_conf_end_event(struct confbridge_conference *conference)
521 {
522         send_conf_stasis(conference, NULL, confbridge_end_type(), NULL, 0);
523 }
524
525 static void send_join_event(struct confbridge_user *user, struct confbridge_conference *conference)
526 {
527         struct ast_json *json_object;
528
529         json_object = ast_json_pack("{s: b}",
530                 "admin", ast_test_flag(&user->u_profile, USER_OPT_ADMIN)
531         );
532         if (!json_object) {
533                 return;
534         }
535         send_conf_stasis(conference, user->chan, confbridge_join_type(), json_object, 0);
536         ast_json_unref(json_object);
537 }
538
539 static void send_leave_event(struct confbridge_user *user, struct confbridge_conference *conference)
540 {
541         struct ast_json *json_object;
542
543         json_object = ast_json_pack("{s: b}",
544                 "admin", ast_test_flag(&user->u_profile, USER_OPT_ADMIN)
545         );
546         if (!json_object) {
547                 return;
548         }
549         send_conf_stasis(conference, user->chan, confbridge_leave_type(), json_object, 0);
550         ast_json_unref(json_object);
551 }
552
553 static void send_start_record_event(struct confbridge_conference *conference)
554 {
555         send_conf_stasis(conference, NULL, confbridge_start_record_type(), NULL, 0);
556 }
557
558 static void send_stop_record_event(struct confbridge_conference *conference)
559 {
560         send_conf_stasis(conference, NULL, confbridge_stop_record_type(), NULL, 0);
561 }
562
563 static void send_mute_event(struct confbridge_user *user, struct confbridge_conference *conference)
564 {
565         struct ast_json *json_object;
566
567         json_object = ast_json_pack("{s: b}",
568                 "admin", ast_test_flag(&user->u_profile, USER_OPT_ADMIN)
569         );
570         if (!json_object) {
571                 return;
572         }
573         send_conf_stasis(conference, user->chan, confbridge_mute_type(), json_object, 1);
574         ast_json_unref(json_object);
575 }
576
577 static void send_unmute_event(struct confbridge_user *user, struct confbridge_conference *conference)
578 {
579         struct ast_json *json_object;
580
581         json_object = ast_json_pack("{s: b}",
582                 "admin", ast_test_flag(&user->u_profile, USER_OPT_ADMIN)
583         );
584         if (!json_object) {
585                 return;
586         }
587         send_conf_stasis(conference, user->chan, confbridge_unmute_type(), json_object, 1);
588         ast_json_unref(json_object);
589 }
590
591 static void set_rec_filename(struct confbridge_conference *conference, struct ast_str **filename, int is_new)
592 {
593         char *rec_file = conference->b_profile.rec_file;
594         char *ext;
595         time_t now;
596
597         if (ast_str_strlen(*filename)
598                 && ast_test_flag(&conference->b_profile, BRIDGE_OPT_RECORD_FILE_APPEND)
599                 && !is_new) {
600                 return;
601         }
602
603         time(&now);
604
605         ast_str_reset(*filename);
606         if (ast_strlen_zero(rec_file)) {
607                 ast_str_set(filename, 0, "confbridge-%s-%u.wav", conference->name,
608                         (unsigned int) now);
609         } else if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_RECORD_FILE_TIMESTAMP)) {
610                 /* insert time before file extension */
611                 ext = strrchr(rec_file, '.');
612                 if (ext) {
613                         ast_str_set_substr(filename, 0, rec_file, ext - rec_file);
614                         ast_str_append(filename, 0, "-%u%s", (unsigned int) now, ext);
615                 } else {
616                         ast_str_set(filename, 0, "%s-%u", rec_file, (unsigned int) now);
617                 }
618         } else {
619                 ast_str_set(filename, 0, "%s", rec_file);
620         }
621         ast_str_append(filename, 0, ",%s%s,%s",
622                 ast_test_flag(&conference->b_profile, BRIDGE_OPT_RECORD_FILE_APPEND) ? "a" : "",
623                 conference->b_profile.rec_options,
624                 conference->b_profile.rec_command);
625 }
626
627 static int is_new_rec_file(const char *rec_file, struct ast_str **orig_rec_file)
628 {
629         if (!ast_strlen_zero(rec_file)) {
630                 if (!*orig_rec_file) {
631                         *orig_rec_file = ast_str_create(RECORD_FILENAME_INITIAL_SPACE);
632                 }
633
634                 if (*orig_rec_file
635                         && strcmp(ast_str_buffer(*orig_rec_file), rec_file)) {
636                         ast_str_set(orig_rec_file, 0, "%s", rec_file);
637                         return 1;
638                 }
639         }
640         return 0;
641 }
642
643 /*!
644  * \internal
645  * \brief Returns whether or not conference is being recorded.
646  *
647  * \param conference The bridge to check for recording
648  *
649  * \note Must be called with the conference locked
650  *
651  * \retval 1, conference is recording.
652  * \retval 0, conference is NOT recording.
653  */
654 static int conf_is_recording(struct confbridge_conference *conference)
655 {
656         return conference->record_chan != NULL;
657 }
658
659 /*!
660  * \internal
661  * \brief Stop recording a conference bridge
662  *
663  * \param conference The conference bridge on which to stop the recording
664  *
665  * \note Must be called with the conference locked
666  *
667  * \retval -1 Failure
668  * \retval 0 Success
669  */
670 static int conf_stop_record(struct confbridge_conference *conference)
671 {
672         struct ast_channel *chan;
673         struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_HANGUP };
674
675         if (!conf_is_recording(conference)) {
676                 return -1;
677         }
678
679         /* Remove the recording channel from the conference bridge. */
680         chan = conference->record_chan;
681         conference->record_chan = NULL;
682         ast_queue_frame(chan, &f);
683         ast_channel_unref(chan);
684
685         ast_test_suite_event_notify("CONF_STOP_RECORD", "Message: stopped conference recording channel\r\nConference: %s", conference->b_profile.name);
686         send_stop_record_event(conference);
687
688         return 0;
689 }
690
691 /*!
692  * \internal
693  * \brief Start recording the conference
694  *
695  * \param conference The conference bridge to start recording
696  *
697  * \note Must be called with the conference locked
698  *
699  * \retval 0 success
700  * \retval non-zero failure
701  */
702 static int conf_start_record(struct confbridge_conference *conference)
703 {
704         struct ast_app *mixmonapp;
705         struct ast_channel *chan;
706         struct ast_format_cap *cap;
707         struct ast_bridge_features *features;
708
709         if (conf_is_recording(conference)) {
710                 return -1;
711         }
712
713         mixmonapp = pbx_findapp("MixMonitor");
714         if (!mixmonapp) {
715                 ast_log(LOG_WARNING, "Cannot record ConfBridge, MixMonitor app is not installed\n");
716                 return -1;
717         }
718
719         features = ast_bridge_features_new();
720         if (!features) {
721                 return -1;
722         }
723         ast_set_flag(&features->feature_flags, AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE);
724
725         cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
726         if (!cap) {
727                 ast_bridge_features_destroy(features);
728                 return -1;
729         }
730         ast_format_cap_append(cap, ast_format_slin, 0);
731
732         /* Create the recording channel. */
733         chan = ast_request("CBRec", cap, NULL, NULL, conference->name, NULL);
734         ao2_ref(cap, -1);
735         if (!chan) {
736                 ast_bridge_features_destroy(features);
737                 return -1;
738         }
739
740         /* Start recording. */
741         set_rec_filename(conference, &conference->record_filename,
742                 is_new_rec_file(conference->b_profile.rec_file, &conference->orig_rec_file));
743         ast_answer(chan);
744         pbx_exec(chan, mixmonapp, ast_str_buffer(conference->record_filename));
745
746         /* Put the channel into the conference bridge. */
747         ast_channel_ref(chan);
748         conference->record_chan = chan;
749         if (ast_bridge_impart(conference->bridge, chan, NULL, features,
750                 AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) {
751                 ast_hangup(chan);
752                 ast_channel_unref(chan);
753                 conference->record_chan = NULL;
754                 return -1;
755         }
756
757         ast_test_suite_event_notify("CONF_START_RECORD", "Message: started conference recording channel\r\nConference: %s", conference->b_profile.name);
758         send_start_record_event(conference);
759
760         return 0;
761 }
762
763 /* \brief Playback the given filename and monitor for any dtmf interrupts.
764  *
765  * This function is used to playback sound files on a given channel and optionally
766  * allow dtmf interrupts to occur.
767  *
768  * If the optional bridge_channel parameter is given then sound file playback
769  * is played on that channel and dtmf interruptions are allowed. However, if
770  * bridge_channel is not set then the channel parameter is expected to be set
771  * instead and non interruptible playback is played on that channel.
772  *
773  * \param bridge_channel Bridge channel to play file on
774  * \param channel Optional channel to play file on if bridge_channel not given
775  * \param filename The file name to playback
776  *
777  * \retval -1 failure during playback, 0 on file was fully played, 1 on dtmf interrupt.
778  */
779 static int play_file(struct ast_bridge_channel *bridge_channel, struct ast_channel *channel,
780                      const char *filename)
781 {
782         struct ast_channel *chan;
783         const char *stop_digits;
784         int digit;
785
786         if (bridge_channel) {
787                 chan = bridge_channel->chan;
788                 stop_digits = AST_DIGIT_ANY;
789         } else {
790                 chan = channel;
791                 stop_digits = AST_DIGIT_NONE;
792         }
793
794         digit = ast_stream_and_wait(chan, filename, stop_digits);
795         if (digit < 0) {
796                 ast_log(LOG_WARNING, "Failed to playback file '%s' to channel\n", filename);
797                 return -1;
798         }
799
800         if (digit > 0) {
801                 ast_stopstream(bridge_channel->chan);
802                 ast_bridge_channel_feature_digit_add(bridge_channel, digit);
803                 return 1;
804         }
805
806         return 0;
807 }
808
809 /*!
810  * \internal
811  * \brief Complain if the given sound file does not exist.
812  *
813  * \param filename Sound file to check if exists.
814  *
815  * \retval non-zero if the file exists.
816  */
817 static int sound_file_exists(const char *filename)
818 {
819         if (ast_fileexists(filename, NULL, NULL)) {
820                 return -1;
821         }
822         ast_log(LOG_WARNING, "File %s does not exist in any format\n", filename);
823         return 0;
824 }
825
826 /*!
827  * \brief Announce number of users in the conference bridge to the caller
828  *
829  * \param conference Conference bridge to peek at
830  * \param user Optional Caller
831  * \param bridge_channel The bridged channel involved
832  *
833  * \note if caller is NULL, the announcment will be sent to all participants in the conference.
834  * \return Returns 0 on success, -1 if the user hung up
835  */
836 static int announce_user_count(struct confbridge_conference *conference, struct confbridge_user *user,
837                                struct ast_bridge_channel *bridge_channel)
838 {
839         const char *other_in_party = conf_get_sound(CONF_SOUND_OTHER_IN_PARTY, conference->b_profile.sounds);
840         const char *only_one = conf_get_sound(CONF_SOUND_ONLY_ONE, conference->b_profile.sounds);
841         const char *there_are = conf_get_sound(CONF_SOUND_THERE_ARE, conference->b_profile.sounds);
842
843         if (conference->activeusers <= 1) {
844                 /* Awww we are the only person in the conference bridge OR we only have waitmarked users */
845                 return 0;
846         } else if (conference->activeusers == 2) {
847                 if (user) {
848                         /* Eep, there is one other person */
849                         if (play_file(bridge_channel, user->chan, only_one) < 0) {
850                                 return -1;
851                         }
852                 } else {
853                         play_sound_file(conference, only_one);
854                 }
855         } else {
856                 /* Alas multiple others in here */
857                 if (user) {
858                         if (ast_stream_and_wait(user->chan,
859                                 there_are,
860                                 "")) {
861                                 return -1;
862                         }
863                         if (ast_say_number(user->chan, conference->activeusers - 1, "", ast_channel_language(user->chan), NULL)) {
864                                 return -1;
865                         }
866                         if (play_file(bridge_channel, user->chan, other_in_party) < 0) {
867                                 return -1;
868                         }
869                 } else if (sound_file_exists(there_are) && sound_file_exists(other_in_party)) {
870                         play_sound_file(conference, there_are);
871                         play_sound_number(conference, conference->activeusers - 1);
872                         play_sound_file(conference, other_in_party);
873                 }
874         }
875         return 0;
876 }
877
878 /*!
879  * \brief Play back an audio file to a channel
880  *
881  * \param user User to play audio prompt to
882  * \param filename Prompt to play
883  *
884  * \return Returns 0 on success, -1 if the user hung up
885  * \note Generally this should be called when the conference is unlocked to avoid blocking
886  * the entire conference while the sound is played. But don't unlock the conference bridge
887  * in the middle of a state transition.
888  */
889 static int play_prompt_to_user(struct confbridge_user *user, const char *filename)
890 {
891         return ast_stream_and_wait(user->chan, filename, "");
892 }
893
894 static void handle_video_on_join(struct confbridge_conference *conference, struct ast_channel *chan, int marked)
895 {
896         /* Right now, only marked users are automatically set as the single src of video.*/
897         if (!marked) {
898                 return;
899         }
900
901         if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED)) {
902                 int set = 1;
903                 struct confbridge_user *user = NULL;
904
905                 ao2_lock(conference);
906                 /* see if anyone is already the video src */
907                 AST_LIST_TRAVERSE(&conference->active_list, user, list) {
908                         if (user->chan == chan) {
909                                 continue;
910                         }
911                         if (ast_bridge_is_video_src(conference->bridge, user->chan)) {
912                                 set = 0;
913                                 break;
914                         }
915                 }
916                 ao2_unlock(conference);
917                 if (set) {
918                         ast_bridge_set_single_src_video_mode(conference->bridge, chan);
919                 }
920         } else if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_VIDEO_SRC_LAST_MARKED)) {
921                 /* we joined and are video capable, we override anyone else that may have already been the video feed */
922                 ast_bridge_set_single_src_video_mode(conference->bridge, chan);
923         }
924 }
925
926 static void handle_video_on_exit(struct confbridge_conference *conference, struct ast_channel *chan)
927 {
928         struct confbridge_user *user = NULL;
929
930         /* if this isn't a video source, nothing to update */
931         if (!ast_bridge_is_video_src(conference->bridge, chan)) {
932                 return;
933         }
934
935         ast_bridge_remove_video_src(conference->bridge, chan);
936
937         /* If in follow talker mode, make sure to restore this mode on the
938          * bridge when a source is removed.  It is possible this channel was
939          * only set temporarily as a video source by an AMI or DTMF action. */
940         if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER)) {
941                 ast_bridge_set_talker_src_video_mode(conference->bridge);
942         }
943
944         /* if the video_mode isn't set to automatically pick the video source, do nothing on exit. */
945         if (!ast_test_flag(&conference->b_profile, BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED) &&
946                 !ast_test_flag(&conference->b_profile, BRIDGE_OPT_VIDEO_SRC_LAST_MARKED)) {
947                 return;
948         }
949
950         /* Make the next available marked user the video src.  */
951         ao2_lock(conference);
952         AST_LIST_TRAVERSE(&conference->active_list, user, list) {
953                 if (user->chan == chan) {
954                         continue;
955                 }
956                 if (ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER)) {
957                         ast_bridge_set_single_src_video_mode(conference->bridge, user->chan);
958                         break;
959                 }
960         }
961         ao2_unlock(conference);
962 }
963
964 struct hangup_data
965 {
966         struct confbridge_conference *conference;
967         ast_mutex_t lock;
968         ast_cond_t cond;
969         int hungup;
970 };
971
972 /*!
973  * \brief Hang up the announcer channel
974  *
975  * This hangs up the announcer channel in the conference. This
976  * runs in the playback queue taskprocessor since we do not want
977  * to hang up the channel while it's trying to play an announcement.
978  *
979  * This task is performed synchronously, so there is no need to
980  * perform any cleanup on the passed-in data.
981  *
982  * \param data A hangup_data structure
983  * \return 0
984  */
985 static int hangup_playback(void *data)
986 {
987         struct hangup_data *hangup = data;
988
989         ast_autoservice_stop(hangup->conference->playback_chan);
990
991         ast_hangup(hangup->conference->playback_chan);
992         hangup->conference->playback_chan = NULL;
993
994         ast_mutex_lock(&hangup->lock);
995         hangup->hungup = 1;
996         ast_cond_signal(&hangup->cond);
997         ast_mutex_unlock(&hangup->lock);
998
999         return 0;
1000 }
1001
1002 static void hangup_data_init(struct hangup_data *hangup, struct confbridge_conference *conference)
1003 {
1004         ast_mutex_init(&hangup->lock);
1005         ast_cond_init(&hangup->cond, NULL);
1006
1007         hangup->conference = conference;
1008         hangup->hungup = 0;
1009 }
1010
1011 static void hangup_data_destroy(struct hangup_data *hangup)
1012 {
1013         ast_mutex_destroy(&hangup->lock);
1014         ast_cond_destroy(&hangup->cond);
1015 }
1016
1017 /*!
1018  * \brief Destroy a conference bridge
1019  *
1020  * \param obj The conference bridge object
1021  *
1022  * \return Returns nothing
1023  */
1024 static void destroy_conference_bridge(void *obj)
1025 {
1026         struct confbridge_conference *conference = obj;
1027
1028         ast_debug(1, "Destroying conference bridge '%s'\n", conference->name);
1029
1030         if (conference->playback_chan) {
1031                 if (conference->playback_queue) {
1032                         struct hangup_data hangup;
1033                         hangup_data_init(&hangup, conference);
1034                         ast_taskprocessor_push(conference->playback_queue, hangup_playback, &hangup);
1035
1036                         ast_mutex_lock(&hangup.lock);
1037                         while (!hangup.hungup) {
1038                                 ast_cond_wait(&hangup.cond, &hangup.lock);
1039                         }
1040                         ast_mutex_unlock(&hangup.lock);
1041                         hangup_data_destroy(&hangup);
1042                 } else {
1043                         /* Playback queue is not yet allocated. Just hang up the channel straight */
1044                         ast_hangup(conference->playback_chan);
1045                         conference->playback_chan = NULL;
1046                 }
1047         }
1048
1049         /* Destroying a conference bridge is simple, all we have to do is destroy the bridging object */
1050         if (conference->bridge) {
1051                 ast_bridge_destroy(conference->bridge, 0);
1052                 conference->bridge = NULL;
1053         }
1054
1055         ast_channel_cleanup(conference->record_chan);
1056         ast_free(conference->orig_rec_file);
1057         ast_free(conference->record_filename);
1058
1059         conf_bridge_profile_destroy(&conference->b_profile);
1060         ast_taskprocessor_unreference(conference->playback_queue);
1061 }
1062
1063 /*! \brief Call the proper join event handler for the user for the conference bridge's current state
1064  * \internal
1065  * \param user The conference bridge user that is joining
1066  * \retval 0 success
1067  * \retval -1 failure
1068  */
1069 static int handle_conf_user_join(struct confbridge_user *user)
1070 {
1071         conference_event_fn handler;
1072         if (ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER)) {
1073                 handler = user->conference->state->join_marked;
1074         } else if (ast_test_flag(&user->u_profile, USER_OPT_WAITMARKED)) {
1075                 handler = user->conference->state->join_waitmarked;
1076         } else {
1077                 handler = user->conference->state->join_unmarked;
1078         }
1079
1080         ast_assert(handler != NULL);
1081
1082         if (!handler) {
1083                 conf_invalid_event_fn(user);
1084                 return -1;
1085         }
1086
1087         handler(user);
1088
1089         return 0;
1090 }
1091
1092 /*! \brief Call the proper leave event handler for the user for the conference bridge's current state
1093  * \internal
1094  * \param user The conference bridge user that is leaving
1095  * \retval 0 success
1096  * \retval -1 failure
1097  */
1098 static int handle_conf_user_leave(struct confbridge_user *user)
1099 {
1100         conference_event_fn handler;
1101         if (ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER)) {
1102                 handler = user->conference->state->leave_marked;
1103         } else if (ast_test_flag(&user->u_profile, USER_OPT_WAITMARKED)) {
1104                 handler = user->conference->state->leave_waitmarked;
1105         } else {
1106                 handler = user->conference->state->leave_unmarked;
1107         }
1108
1109         ast_assert(handler != NULL);
1110
1111         if (!handler) {
1112                 /* This should never happen. If it does, though, it is bad. The user will not have been removed
1113                  * from the appropriate list, so counts will be off and stuff. The conference won't be torn down, etc.
1114                  * Shouldn't happen, though. */
1115                 conf_invalid_event_fn(user);
1116                 return -1;
1117         }
1118
1119         handler(user);
1120
1121         return 0;
1122 }
1123
1124 void conf_update_user_mute(struct confbridge_user *user)
1125 {
1126         int mute_user;
1127         int mute_system;
1128         int mute_effective;
1129
1130         /* User level mute request. */
1131         mute_user = user->muted;
1132
1133         /* System level mute request. */
1134         mute_system = user->playing_moh
1135                 /*
1136                  * Do not allow waitmarked users to talk to anyone unless there
1137                  * is a marked user present.
1138                  */
1139                 || (!user->conference->markedusers
1140                         && ast_test_flag(&user->u_profile, USER_OPT_WAITMARKED));
1141
1142         mute_effective = mute_user || mute_system;
1143
1144         ast_debug(1, "User %s is %s: user:%d system:%d.\n",
1145                 ast_channel_name(user->chan), mute_effective ? "muted" : "unmuted",
1146                 mute_user, mute_system);
1147         user->features.mute = mute_effective;
1148         ast_test_suite_event_notify("CONF_MUTE_UPDATE",
1149                 "Mode: %s\r\n"
1150                 "Conference: %s\r\n"
1151                 "Channel: %s",
1152                 mute_effective ? "muted" : "unmuted",
1153                 user->conference->b_profile.name,
1154                 ast_channel_name(user->chan));
1155 }
1156
1157 /*
1158  * \internal
1159  * \brief Mute/unmute a single user.
1160  */
1161 static void generic_mute_unmute_user(struct confbridge_conference *conference, struct confbridge_user *user, int mute)
1162 {
1163         /* Set user level mute request. */
1164         user->muted = mute ? 1 : 0;
1165
1166         conf_update_user_mute(user);
1167         ast_test_suite_event_notify("CONF_MUTE",
1168                 "Message: participant %s %s\r\n"
1169                 "Conference: %s\r\n"
1170                 "Channel: %s",
1171                 ast_channel_name(user->chan),
1172                 mute ? "muted" : "unmuted",
1173                 conference->b_profile.name,
1174                 ast_channel_name(user->chan));
1175         if (mute) {
1176                 send_mute_event(user, conference);
1177         } else {
1178                 send_unmute_event(user, conference);
1179         }
1180 }
1181
1182 void conf_moh_stop(struct confbridge_user *user)
1183 {
1184         user->playing_moh = 0;
1185         if (!user->suspended_moh) {
1186                 int in_bridge;
1187
1188                 /*
1189                  * Locking the ast_bridge here is the only way to hold off the
1190                  * call to ast_bridge_join() in confbridge_exec() from
1191                  * interfering with the bridge and MOH operations here.
1192                  */
1193                 ast_bridge_lock(user->conference->bridge);
1194
1195                 /*
1196                  * Temporarily suspend the user from the bridge so we have
1197                  * control to stop MOH if needed.
1198                  */
1199                 in_bridge = !ast_bridge_suspend(user->conference->bridge, user->chan);
1200                 ast_moh_stop(user->chan);
1201                 if (in_bridge) {
1202                         ast_bridge_unsuspend(user->conference->bridge, user->chan);
1203                 }
1204
1205                 ast_bridge_unlock(user->conference->bridge);
1206         }
1207 }
1208
1209 void conf_moh_start(struct confbridge_user *user)
1210 {
1211         user->playing_moh = 1;
1212         if (!user->suspended_moh) {
1213                 int in_bridge;
1214
1215                 /*
1216                  * Locking the ast_bridge here is the only way to hold off the
1217                  * call to ast_bridge_join() in confbridge_exec() from
1218                  * interfering with the bridge and MOH operations here.
1219                  */
1220                 ast_bridge_lock(user->conference->bridge);
1221
1222                 /*
1223                  * Temporarily suspend the user from the bridge so we have
1224                  * control to start MOH if needed.
1225                  */
1226                 in_bridge = !ast_bridge_suspend(user->conference->bridge, user->chan);
1227                 ast_moh_start(user->chan, user->u_profile.moh_class, NULL);
1228                 if (in_bridge) {
1229                         ast_bridge_unsuspend(user->conference->bridge, user->chan);
1230                 }
1231
1232                 ast_bridge_unlock(user->conference->bridge);
1233         }
1234 }
1235
1236 /*!
1237  * \internal
1238  * \brief Unsuspend MOH for the conference user.
1239  *
1240  * \param user Conference user to unsuspend MOH on.
1241  *
1242  * \return Nothing
1243  */
1244 static void conf_moh_unsuspend(struct confbridge_user *user)
1245 {
1246         ao2_lock(user->conference);
1247         if (--user->suspended_moh == 0 && user->playing_moh) {
1248                 ast_moh_start(user->chan, user->u_profile.moh_class, NULL);
1249         }
1250         ao2_unlock(user->conference);
1251 }
1252
1253 /*!
1254  * \internal
1255  * \brief Suspend MOH for the conference user.
1256  *
1257  * \param user Conference user to suspend MOH on.
1258  *
1259  * \return Nothing
1260  */
1261 static void conf_moh_suspend(struct confbridge_user *user)
1262 {
1263         ao2_lock(user->conference);
1264         if (user->suspended_moh++ == 0 && user->playing_moh) {
1265                 ast_moh_stop(user->chan);
1266         }
1267         ao2_unlock(user->conference);
1268 }
1269
1270 int conf_handle_inactive_waitmarked(struct confbridge_user *user)
1271 {
1272         /* If we have not been quieted play back that they are waiting for the leader */
1273         if (!ast_test_flag(&user->u_profile, USER_OPT_QUIET) && play_prompt_to_user(user,
1274                         conf_get_sound(CONF_SOUND_WAIT_FOR_LEADER, user->conference->b_profile.sounds))) {
1275                 /* user hungup while the sound was playing */
1276                 return -1;
1277         }
1278         return 0;
1279 }
1280
1281 int conf_handle_only_unmarked(struct confbridge_user *user)
1282 {
1283         /* If audio prompts have not been quieted or this prompt quieted play it on out */
1284         if (!ast_test_flag(&user->u_profile, USER_OPT_QUIET | USER_OPT_NOONLYPERSON)) {
1285                 if (play_prompt_to_user(user,
1286                         conf_get_sound(CONF_SOUND_ONLY_PERSON, user->conference->b_profile.sounds))) {
1287                         /* user hungup while the sound was playing */
1288                         return -1;
1289                 }
1290         }
1291         return 0;
1292 }
1293
1294 int conf_add_post_join_action(struct confbridge_user *user, int (*func)(struct confbridge_user *user))
1295 {
1296         struct post_join_action *action;
1297         if (!(action = ast_calloc(1, sizeof(*action)))) {
1298                 return -1;
1299         }
1300         action->func = func;
1301         AST_LIST_INSERT_TAIL(&user->post_join_list, action, list);
1302         return 0;
1303 }
1304
1305
1306 void conf_handle_first_join(struct confbridge_conference *conference)
1307 {
1308         ast_devstate_changed(AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, "confbridge:%s", conference->name);
1309 }
1310
1311 void conf_handle_second_active(struct confbridge_conference *conference)
1312 {
1313         /* If we are the second participant we may need to stop music on hold on the first */
1314         struct confbridge_user *first_user = AST_LIST_FIRST(&conference->active_list);
1315
1316         if (ast_test_flag(&first_user->u_profile, USER_OPT_MUSICONHOLD)) {
1317                 conf_moh_stop(first_user);
1318         }
1319         conf_update_user_mute(first_user);
1320 }
1321
1322 void conf_ended(struct confbridge_conference *conference)
1323 {
1324         struct pbx_find_info q = { .stacklen = 0 };
1325
1326         /* Called with a reference to conference */
1327         ao2_unlink(conference_bridges, conference);
1328         send_conf_end_event(conference);
1329         if (!ast_strlen_zero(conference->b_profile.regcontext) &&
1330                         pbx_find_extension(NULL, NULL, &q, conference->b_profile.regcontext,
1331                                 conference->name, 1, NULL, "", E_MATCH)) {
1332                 ast_context_remove_extension(conference->b_profile.regcontext,
1333                                 conference->name, 1, NULL);
1334         }
1335         ao2_lock(conference);
1336         conf_stop_record(conference);
1337         ao2_unlock(conference);
1338 }
1339
1340 /*!
1341  * \internal
1342  * \brief Allocate playback channel for a conference.
1343  * \pre expects conference to be locked before calling this function
1344  */
1345 static int alloc_playback_chan(struct confbridge_conference *conference)
1346 {
1347         struct ast_format_cap *cap;
1348         char taskprocessor_name[AST_TASKPROCESSOR_MAX_NAME + 1];
1349
1350         cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
1351         if (!cap) {
1352                 return -1;
1353         }
1354         ast_format_cap_append(cap, ast_format_slin, 0);
1355         conference->playback_chan = ast_request("CBAnn", cap, NULL, NULL,
1356                 conference->name, NULL);
1357         ao2_ref(cap, -1);
1358         if (!conference->playback_chan) {
1359                 return -1;
1360         }
1361
1362         /* To make sure playback_chan has the same language as the bridge */
1363         ast_channel_lock(conference->playback_chan);
1364         ast_channel_language_set(conference->playback_chan, conference->b_profile.language);
1365         ast_channel_unlock(conference->playback_chan);
1366
1367         ast_debug(1, "Created announcer channel '%s' to conference bridge '%s'\n",
1368                 ast_channel_name(conference->playback_chan), conference->name);
1369
1370         ast_taskprocessor_build_name(taskprocessor_name, sizeof(taskprocessor_name),
1371                 "Confbridge/%s", conference->name);
1372         conference->playback_queue = ast_taskprocessor_get(taskprocessor_name, TPS_REF_DEFAULT);
1373         if (!conference->playback_queue) {
1374                 ast_hangup(conference->playback_chan);
1375                 conference->playback_chan = NULL;
1376                 return -1;
1377         }
1378         return 0;
1379 }
1380
1381 /*!
1382  * \brief Push the announcer channel into the bridge
1383  *
1384  * This runs in the playback queue taskprocessor.
1385  *
1386  * \param data A confbridge_conference
1387  * \retval 0 Success
1388  * \retval -1 Failed to push the channel to the bridge
1389  */
1390 static int push_announcer(void *data)
1391 {
1392         struct confbridge_conference *conference = data;
1393
1394         if (conf_announce_channel_push(conference->playback_chan)) {
1395                 ast_hangup(conference->playback_chan);
1396                 conference->playback_chan = NULL;
1397                 ao2_cleanup(conference);
1398                 return -1;
1399         }
1400
1401         ast_autoservice_start(conference->playback_chan);
1402         ao2_cleanup(conference);
1403         return 0;
1404 }
1405
1406 /*!
1407  * \brief Join a conference bridge
1408  *
1409  * \param conference_name The conference name
1410  * \param user Conference bridge user structure
1411  *
1412  * \return A pointer to the conference bridge struct, or NULL if the conference room wasn't found.
1413  */
1414 static struct confbridge_conference *join_conference_bridge(const char *conference_name, struct confbridge_user *user)
1415 {
1416         struct confbridge_conference *conference;
1417         struct post_join_action *action;
1418         int max_members_reached = 0;
1419
1420         /* We explictly lock the conference bridges container ourselves so that other callers can not create duplicate conferences at the same */
1421         ao2_lock(conference_bridges);
1422
1423         ast_debug(1, "Trying to find conference bridge '%s'\n", conference_name);
1424
1425         /* Attempt to find an existing conference bridge */
1426         conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
1427         if (conference && conference->b_profile.max_members) {
1428                 max_members_reached = conference->b_profile.max_members > conference->activeusers ? 0 : 1;
1429         }
1430
1431         /* When finding a conference bridge that already exists make sure that it is not locked, and if so that we are not an admin */
1432         if (conference && (max_members_reached || conference->locked) && !ast_test_flag(&user->u_profile, USER_OPT_ADMIN)) {
1433                 ao2_unlock(conference_bridges);
1434                 ast_debug(1, "Conference '%s' is locked and caller is not an admin\n", conference_name);
1435                 ast_stream_and_wait(user->chan,
1436                         conf_get_sound(CONF_SOUND_LOCKED, conference->b_profile.sounds),
1437                         "");
1438                 ao2_ref(conference, -1);
1439                 return NULL;
1440         }
1441
1442         /* If no conference bridge was found see if we can create one */
1443         if (!conference) {
1444                 /* Try to allocate memory for a new conference bridge, if we fail... this won't end well. */
1445                 if (!(conference = ao2_alloc(sizeof(*conference), destroy_conference_bridge))) {
1446                         ao2_unlock(conference_bridges);
1447                         ast_log(LOG_ERROR, "Conference '%s' could not be created.\n", conference_name);
1448                         return NULL;
1449                 }
1450
1451                 /* Setup for the record channel */
1452                 conference->record_filename = ast_str_create(RECORD_FILENAME_INITIAL_SPACE);
1453                 if (!conference->record_filename) {
1454                         ao2_ref(conference, -1);
1455                         ao2_unlock(conference_bridges);
1456                         return NULL;
1457                 }
1458
1459                 /* Setup conference bridge parameters */
1460                 ast_copy_string(conference->name, conference_name, sizeof(conference->name));
1461                 conf_bridge_profile_copy(&conference->b_profile, &user->b_profile);
1462
1463                 /* Create an actual bridge that will do the audio mixing */
1464                 conference->bridge = ast_bridge_base_new(AST_BRIDGE_CAPABILITY_MULTIMIX,
1465                         AST_BRIDGE_FLAG_MASQUERADE_ONLY | AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY,
1466                         app, conference_name, NULL);
1467                 if (!conference->bridge) {
1468                         ao2_ref(conference, -1);
1469                         ao2_unlock(conference_bridges);
1470                         ast_log(LOG_ERROR, "Conference '%s' mixing bridge could not be created.\n", conference_name);
1471                         return NULL;
1472                 }
1473
1474                 /* Set the internal sample rate on the bridge from the bridge profile */
1475                 ast_bridge_set_internal_sample_rate(conference->bridge, conference->b_profile.internal_sample_rate);
1476                 /* Set the internal mixing interval on the bridge from the bridge profile */
1477                 ast_bridge_set_mixing_interval(conference->bridge, conference->b_profile.mix_interval);
1478                 ast_bridge_set_binaural_active(conference->bridge, ast_test_flag(&conference->b_profile, BRIDGE_OPT_BINAURAL_ACTIVE));
1479
1480                 if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER)) {
1481                         ast_bridge_set_talker_src_video_mode(conference->bridge);
1482                 }
1483
1484                 /* Link it into the conference bridges container */
1485                 if (!ao2_link(conference_bridges, conference)) {
1486                         ao2_ref(conference, -1);
1487                         ao2_unlock(conference_bridges);
1488                         ast_log(LOG_ERROR,
1489                                 "Conference '%s' could not be added to the conferences list.\n", conference_name);
1490                         return NULL;
1491                 }
1492
1493                 /* Set the initial state to EMPTY */
1494                 conference->state = CONF_STATE_EMPTY;
1495
1496                 if (alloc_playback_chan(conference)) {
1497                         ao2_unlink(conference_bridges, conference);
1498                         ao2_ref(conference, -1);
1499                         ao2_unlock(conference_bridges);
1500                         ast_log(LOG_ERROR, "Could not allocate announcer channel for conference '%s'\n", conference_name);
1501                         return NULL;
1502                 }
1503
1504                 if (ast_taskprocessor_push(conference->playback_queue, push_announcer, ao2_bump(conference))) {
1505                         ao2_unlink(conference_bridges, conference);
1506                         ao2_ref(conference, -1);
1507                         ao2_unlock(conference_bridges);
1508                         ast_log(LOG_ERROR, "Could not add announcer channel for conference '%s' bridge\n", conference_name);
1509                         return NULL;
1510                 }
1511
1512                 if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_RECORD_CONFERENCE)) {
1513                         ao2_lock(conference);
1514                         conf_start_record(conference);
1515                         ao2_unlock(conference);
1516                 }
1517
1518                 send_conf_start_event(conference);
1519
1520                 if (!ast_strlen_zero(conference->b_profile.regcontext)) {
1521                         if (!ast_exists_extension(NULL, conference->b_profile.regcontext, conference->name, 1, NULL)) {
1522                                 ast_add_extension(conference->b_profile.regcontext, 1, conference->name, 1, NULL, NULL, "Noop", NULL, NULL, "ConfBridge");
1523                         }
1524                 }
1525
1526                 ast_debug(1, "Created conference '%s' and linked to container.\n", conference_name);
1527         }
1528
1529         ao2_unlock(conference_bridges);
1530
1531         /* Setup conference bridge user parameters */
1532         user->conference = conference;
1533
1534         ao2_lock(conference);
1535
1536         /* Determine if the new user should join the conference muted. */
1537         if (ast_test_flag(&user->u_profile, USER_OPT_STARTMUTED)
1538                 || (!ast_test_flag(&user->u_profile, USER_OPT_ADMIN) && conference->muted)) {
1539                 /* Set user level mute request. */
1540                 user->muted = 1;
1541         }
1542
1543         /*
1544          * Suspend any MOH until the user actually joins the bridge of
1545          * the conference.  This way any pre-join file playback does not
1546          * need to worry about MOH.
1547          */
1548         user->suspended_moh = 1;
1549
1550         if (handle_conf_user_join(user)) {
1551                 /* Invalid event, nothing was done, so we don't want to process a leave. */
1552                 ao2_unlock(conference);
1553                 ao2_ref(conference, -1);
1554                 user->conference = NULL;
1555                 return NULL;
1556         }
1557
1558         if (ast_check_hangup(user->chan)) {
1559                 ao2_unlock(conference);
1560                 leave_conference(user);
1561                 return NULL;
1562         }
1563
1564         ao2_unlock(conference);
1565
1566         /* If an announcement is to be played play it */
1567         if (!ast_strlen_zero(user->u_profile.announcement)) {
1568                 if (play_prompt_to_user(user,
1569                         user->u_profile.announcement)) {
1570                         leave_conference(user);
1571                         return NULL;
1572                 }
1573         }
1574
1575         /* Announce number of users if need be */
1576         if (ast_test_flag(&user->u_profile, USER_OPT_ANNOUNCEUSERCOUNT)) {
1577                 if (announce_user_count(conference, user, NULL)) {
1578                         leave_conference(user);
1579                         return NULL;
1580                 }
1581         }
1582
1583         if (ast_test_flag(&user->u_profile, USER_OPT_ANNOUNCEUSERCOUNTALL) &&
1584                 (conference->activeusers > user->u_profile.announce_user_count_all_after)) {
1585                 int user_count_res;
1586
1587                 /*
1588                  * We have to autoservice the new user because he has not quite
1589                  * joined the conference yet.
1590                  */
1591                 ast_autoservice_start(user->chan);
1592                 user_count_res = announce_user_count(conference, NULL, NULL);
1593                 ast_autoservice_stop(user->chan);
1594                 if (user_count_res) {
1595                         leave_conference(user);
1596                         return NULL;
1597                 }
1598         }
1599
1600         /* Handle post-join actions */
1601         while ((action = AST_LIST_REMOVE_HEAD(&user->post_join_list, list))) {
1602                 action->func(user);
1603                 ast_free(action);
1604         }
1605
1606         return conference;
1607 }
1608
1609 /*!
1610  * \brief Leave a conference
1611  *
1612  * \param user The conference user
1613  */
1614 static void leave_conference(struct confbridge_user *user)
1615 {
1616         struct post_join_action *action;
1617
1618         ao2_lock(user->conference);
1619         handle_conf_user_leave(user);
1620         ao2_unlock(user->conference);
1621
1622         /* Discard any post-join actions */
1623         while ((action = AST_LIST_REMOVE_HEAD(&user->post_join_list, list))) {
1624                 ast_free(action);
1625         }
1626
1627         /* Done mucking with the conference, huzzah */
1628         ao2_ref(user->conference, -1);
1629         user->conference = NULL;
1630 }
1631
1632 static void playback_common(struct confbridge_conference *conference, const char *filename, int say_number)
1633 {
1634         /* Don't try to play if the playback channel has been hung up */
1635         if (!conference->playback_chan) {
1636                 return;
1637         }
1638
1639         ast_autoservice_stop(conference->playback_chan);
1640
1641         /* The channel is all under our control, in goes the prompt */
1642         if (!ast_strlen_zero(filename)) {
1643                 ast_stream_and_wait(conference->playback_chan, filename, "");
1644         } else if (say_number >= 0) {
1645                 ast_say_number(conference->playback_chan, say_number, "",
1646                         ast_channel_language(conference->playback_chan), NULL);
1647         }
1648
1649         ast_autoservice_start(conference->playback_chan);
1650 }
1651
1652 struct playback_task_data {
1653         struct confbridge_conference *conference;
1654         const char *filename;
1655         int say_number;
1656         int playback_finished;
1657         ast_mutex_t lock;
1658         ast_cond_t cond;
1659 };
1660
1661 /*!
1662  * \brief Play an announcement into a confbridge
1663  *
1664  * This runs in the playback queue taskprocessor. This ensures that
1665  * all playbacks are handled in sequence and do not play over top one
1666  * another.
1667  *
1668  * This task runs synchronously so there is no need for performing any
1669  * sort of cleanup on the input parameter.
1670  *
1671  * \param data A playback_task_data
1672  * \return 0
1673  */
1674 static int playback_task(void *data)
1675 {
1676         struct playback_task_data *ptd = data;
1677
1678         playback_common(ptd->conference, ptd->filename, ptd->say_number);
1679
1680         ast_mutex_lock(&ptd->lock);
1681         ptd->playback_finished = 1;
1682         ast_cond_signal(&ptd->cond);
1683         ast_mutex_unlock(&ptd->lock);
1684
1685         return 0;
1686 }
1687
1688 static void playback_task_data_init(struct playback_task_data *ptd, struct confbridge_conference *conference,
1689                 const char *filename, int say_number)
1690 {
1691         ast_mutex_init(&ptd->lock);
1692         ast_cond_init(&ptd->cond, NULL);
1693
1694         ptd->filename = filename;
1695         ptd->say_number = say_number;
1696         ptd->conference = conference;
1697         ptd->playback_finished = 0;
1698 }
1699
1700 static void playback_task_data_destroy(struct playback_task_data *ptd)
1701 {
1702         ast_mutex_destroy(&ptd->lock);
1703         ast_cond_destroy(&ptd->cond);
1704 }
1705
1706 static int play_sound_helper(struct confbridge_conference *conference, const char *filename, int say_number)
1707 {
1708         struct playback_task_data ptd;
1709
1710         /* Do not waste resources trying to play files that do not exist */
1711         if (ast_strlen_zero(filename)) {
1712                 if (say_number < 0) {
1713                         return 0;
1714                 }
1715         } else if (!sound_file_exists(filename)) {
1716                 return 0;
1717         }
1718
1719         playback_task_data_init(&ptd, conference, filename, say_number);
1720         if (ast_taskprocessor_push(conference->playback_queue, playback_task, &ptd)) {
1721                 if (!ast_strlen_zero(filename)) {
1722                         ast_log(LOG_WARNING, "Unable to play file '%s' to conference %s\n",
1723                                 filename, conference->name);
1724                 } else {
1725                         ast_log(LOG_WARNING, "Unable to say number '%d' to conference %s\n",
1726                                 say_number, conference->name);
1727                 }
1728                 playback_task_data_destroy(&ptd);
1729                 return -1;
1730         }
1731
1732         /* Wait for the playback to complete */
1733         ast_mutex_lock(&ptd.lock);
1734         while (!ptd.playback_finished) {
1735                 ast_cond_wait(&ptd.cond, &ptd.lock);
1736         }
1737         ast_mutex_unlock(&ptd.lock);
1738
1739         playback_task_data_destroy(&ptd);
1740
1741         return 0;
1742 }
1743
1744 int play_sound_file(struct confbridge_conference *conference, const char *filename)
1745 {
1746         return play_sound_helper(conference, filename, -1);
1747 }
1748
1749 struct async_playback_task_data {
1750         struct confbridge_conference *conference;
1751         int say_number;
1752         struct ast_channel *initiator;
1753         char filename[0];
1754 };
1755
1756 struct async_datastore_data {
1757         ast_mutex_t lock;
1758         ast_cond_t cond;
1759         int wait;
1760 };
1761
1762 static void async_datastore_data_destroy(void *data)
1763 {
1764         struct async_datastore_data *add = data;
1765
1766         ast_mutex_destroy(&add->lock);
1767         ast_cond_destroy(&add->cond);
1768
1769         ast_free(add);
1770 }
1771
1772 /*!
1773  * \brief Datastore used for timing of async announcement playback
1774  *
1775  * Announcements that are played to the entire conference can be played
1776  * asynchronously (i.e. The channel that queues the playback does not wait
1777  * for the playback to complete before continuing)
1778  *
1779  * The thing about async announcements is that the channel that queues the
1780  * announcement is either not in the bridge or is in some other way "occupied"
1781  * at the time the announcement is queued. Because of that, the initiator of
1782  * the announcement may enter after the announcement has already started,
1783  * resulting in the sound being "clipped".
1784  *
1785  * This datastore makes it so that the channel that queues the async announcement
1786  * can say "I'm ready now". This way the announcement does not start until the
1787  * initiator of the announcement is ready to hear the sound.
1788  */
1789 static struct ast_datastore_info async_datastore_info = {
1790         .type = "Confbridge async playback",
1791         .destroy = async_datastore_data_destroy,
1792 };
1793
1794 static struct async_datastore_data *async_datastore_data_alloc(void)
1795 {
1796         struct async_datastore_data *add;
1797
1798         add = ast_malloc(sizeof(*add));
1799         if (!add) {
1800                 return NULL;
1801         }
1802
1803         ast_mutex_init(&add->lock);
1804         ast_cond_init(&add->cond, NULL);
1805         add->wait = 1;
1806
1807         return add;
1808 }
1809
1810 /*!
1811  * \brief Prepare the async playback datastore
1812  *
1813  * This is done prior to queuing an async announcement. If the
1814  * datastore has not yet been created, it is allocated and initialized.
1815  * If it already exists, we set it to be in "waiting" mode.
1816  *
1817  * \param initiator The channel that is queuing the async playback
1818  * \retval 0 Success
1819  * \retval -1 Failure :(
1820  */
1821 static int setup_async_playback_datastore(struct ast_channel *initiator)
1822 {
1823         struct ast_datastore *async_datastore;
1824
1825         async_datastore = ast_channel_datastore_find(initiator, &async_datastore_info, NULL);
1826         if (async_datastore) {
1827                 struct async_datastore_data *add;
1828
1829                 add = async_datastore->data;
1830                 add->wait = 1;
1831
1832                 return 0;
1833         }
1834
1835         async_datastore = ast_datastore_alloc(&async_datastore_info, NULL);
1836         if (!async_datastore) {
1837                 return -1;
1838         }
1839
1840         async_datastore->data = async_datastore_data_alloc();
1841         if (!async_datastore->data) {
1842                 ast_datastore_free(async_datastore);
1843                 return -1;
1844         }
1845
1846         ast_channel_datastore_add(initiator, async_datastore);
1847         return 0;
1848 }
1849
1850 static struct async_playback_task_data *async_playback_task_data_alloc(
1851         struct confbridge_conference *conference, const char *filename, int say_number,
1852         struct ast_channel *initiator)
1853 {
1854         struct async_playback_task_data *aptd;
1855
1856         aptd = ast_malloc(sizeof(*aptd) + strlen(filename) + 1);
1857         if (!aptd) {
1858                 return NULL;
1859         }
1860
1861         /* Safe */
1862         strcpy(aptd->filename, filename);
1863         aptd->say_number = say_number;
1864
1865         /* You may think that we need to bump the conference refcount since we are pushing
1866          * this task to the taskprocessor.
1867          *
1868          * In this case, that actually causes a problem. The destructor for the conference
1869          * pushes a hangup task into the taskprocessor and waits for it to complete before
1870          * continuing. If the destructor gets called from a taskprocessor task, we're
1871          * deadlocked.
1872          *
1873          * So is there a risk of the conference being freed out from under us? No. Since
1874          * the destructor pushes a task into the taskprocessor and waits for it to complete,
1875          * the destructor cannot free the conference out from under us. No further tasks
1876          * can be queued onto the taskprocessor after the hangup since no channels are referencing
1877          * the conference at that point any more.
1878          */
1879         aptd->conference = conference;
1880
1881         aptd->initiator = initiator;
1882         if (initiator) {
1883                 ast_channel_ref(initiator);
1884                 ast_channel_lock(aptd->initiator);
1885                 /* We don't really care if this fails. If the datastore fails to get set up
1886                  * we'll still play the announcement. It's possible that the sound will be
1887                  * clipped for the initiator, but that's not the end of the world.
1888                  */
1889                 setup_async_playback_datastore(aptd->initiator);
1890                 ast_channel_unlock(aptd->initiator);
1891         }
1892
1893         return aptd;
1894 }
1895
1896 static void async_playback_task_data_destroy(struct async_playback_task_data *aptd)
1897 {
1898         ast_channel_cleanup(aptd->initiator);
1899         ast_free(aptd);
1900 }
1901
1902 /*!
1903  * \brief Wait for the initiator of an async playback to be ready
1904  *
1905  * See the description on the async_datastore_info structure for more
1906  * information about what this is about.
1907  *
1908  * \param initiator The channel that queued the async announcement
1909  */
1910 static void wait_for_initiator(struct ast_channel *initiator)
1911 {
1912         struct ast_datastore *async_datastore;
1913         struct async_datastore_data *add;
1914
1915         ast_channel_lock(initiator);
1916         async_datastore = ast_channel_datastore_find(initiator, &async_datastore_info, NULL);
1917         ast_channel_unlock(initiator);
1918
1919         if (!async_datastore) {
1920                 return;
1921         }
1922
1923         add = async_datastore->data;
1924
1925         ast_mutex_lock(&add->lock);
1926         while (add->wait) {
1927                 ast_cond_wait(&add->cond, &add->lock);
1928         }
1929         ast_mutex_unlock(&add->lock);
1930 }
1931
1932 /*!
1933  * \brief Play an announcement into a confbridge asynchronously
1934  *
1935  * This runs in the playback queue taskprocessor. This ensures that
1936  * all playbacks are handled in sequence and do not play over top one
1937  * another.
1938  *
1939  * \param data An async_playback_task_data
1940  * \return 0
1941  */
1942 static int async_playback_task(void *data)
1943 {
1944         struct async_playback_task_data *aptd = data;
1945
1946         /* Wait for the initiator to get back in the bridge or be hung up */
1947         if (aptd->initiator) {
1948                 wait_for_initiator(aptd->initiator);
1949         }
1950
1951         playback_common(aptd->conference, aptd->filename, aptd->say_number);
1952
1953         async_playback_task_data_destroy(aptd);
1954         return 0;
1955 }
1956
1957 static int async_play_sound_helper(struct confbridge_conference *conference,
1958         const char *filename, int say_number, struct ast_channel *initiator)
1959 {
1960         struct async_playback_task_data *aptd;
1961
1962         /* Do not waste resources trying to play files that do not exist */
1963         if (ast_strlen_zero(filename)) {
1964                 if (say_number < 0) {
1965                         return 0;
1966                 }
1967         } else if (!sound_file_exists(filename)) {
1968                 return 0;
1969         }
1970
1971         aptd = async_playback_task_data_alloc(conference, filename, say_number, initiator);
1972         if (!aptd) {
1973                 return -1;
1974         }
1975
1976         if (ast_taskprocessor_push(conference->playback_queue, async_playback_task, aptd)) {
1977                 if (!ast_strlen_zero(filename)) {
1978                         ast_log(LOG_WARNING, "Unable to play file '%s' to conference '%s'\n",
1979                                 filename, conference->name);
1980                 } else {
1981                         ast_log(LOG_WARNING, "Unable to say number '%d' to conference '%s'\n",
1982                                 say_number, conference->name);
1983                 }
1984                 async_playback_task_data_destroy(aptd);
1985                 return -1;
1986         }
1987
1988         return 0;
1989 }
1990
1991 int async_play_sound_file(struct confbridge_conference *conference,
1992         const char *filename, struct ast_channel *initiator)
1993 {
1994         return async_play_sound_helper(conference, filename, -1, initiator);
1995 }
1996
1997 void async_play_sound_ready(struct ast_channel *chan)
1998 {
1999         struct ast_datastore *async_datastore;
2000         struct async_datastore_data *add;
2001
2002         ast_channel_lock(chan);
2003         async_datastore = ast_channel_datastore_find(chan, &async_datastore_info, NULL);
2004         ast_channel_unlock(chan);
2005         if (!async_datastore) {
2006                 return;
2007         }
2008
2009         add = async_datastore->data;
2010
2011         ast_mutex_lock(&add->lock);
2012         add->wait = 0;
2013         ast_cond_signal(&add->cond);
2014         ast_mutex_unlock(&add->lock);
2015 }
2016
2017 /*!
2018  * \brief Play number into the conference bridge
2019  *
2020  * \param conference The conference bridge to say the number into
2021  * \param say_number number to say
2022  *
2023  * \retval 0 success
2024  * \retval -1 failure
2025  */
2026 static int play_sound_number(struct confbridge_conference *conference, int say_number)
2027 {
2028         return play_sound_helper(conference, NULL, say_number);
2029 }
2030
2031 static int conf_handle_talker_cb(struct ast_bridge_channel *bridge_channel, void *hook_pvt, int talking)
2032 {
2033         const struct confbridge_user *user = hook_pvt;
2034         RAII_VAR(struct confbridge_conference *, conference, NULL, ao2_cleanup);
2035         struct ast_json *talking_extras;
2036
2037         conference = ao2_find(conference_bridges, user->conference->name, OBJ_KEY);
2038         if (!conference) {
2039                 /* Remove the hook since the conference does not exist. */
2040                 return -1;
2041         }
2042
2043         talking_extras = ast_json_pack("{s: s, s: b}",
2044                 "talking_status", talking ? "on" : "off",
2045                 "admin", ast_test_flag(&user->u_profile, USER_OPT_ADMIN));
2046         if (!talking_extras) {
2047                 return 0;
2048         }
2049
2050         send_conf_stasis(conference, bridge_channel->chan, confbridge_talking_type(), talking_extras, 0);
2051         ast_json_unref(talking_extras);
2052         return 0;
2053 }
2054
2055 static int conf_get_pin(struct ast_channel *chan, struct confbridge_user *user)
2056 {
2057         char pin_guess[MAX_PIN+1] = { 0, };
2058         const char *pin = user->u_profile.pin;
2059         char *tmp = pin_guess;
2060         int i, res;
2061         unsigned int len = MAX_PIN;
2062
2063         /*
2064          * NOTE: We have not joined a conference yet so we have to use
2065          * the bridge profile requested by the user.
2066          */
2067
2068         /* give them three tries to get the pin right */
2069         for (i = 0; i < 3; i++) {
2070                 if (ast_app_getdata(chan,
2071                         conf_get_sound(CONF_SOUND_GET_PIN, user->b_profile.sounds),
2072                         tmp, len, 0) >= 0) {
2073                         if (!strcasecmp(pin, pin_guess)) {
2074                                 return 0;
2075                         }
2076                 }
2077                 ast_streamfile(chan,
2078                         conf_get_sound(CONF_SOUND_INVALID_PIN, user->b_profile.sounds),
2079                         ast_channel_language(chan));
2080                 res = ast_waitstream(chan, AST_DIGIT_ANY);
2081                 if (res > 0) {
2082                         /* Account for digit already read during ivalid pin playback
2083                          * resetting pin buf. */
2084                         pin_guess[0] = res;
2085                         pin_guess[1] = '\0';
2086                         tmp = pin_guess + 1;
2087                         len = MAX_PIN - 1;
2088                 } else {
2089                         /* reset pin buf as empty buffer. */
2090                         tmp = pin_guess;
2091                         len = MAX_PIN;
2092                 }
2093         }
2094         return -1;
2095 }
2096
2097 static int user_timeout(struct ast_bridge_channel *bridge_channel, void *ignore)
2098 {
2099         ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END, 0);
2100         pbx_builtin_setvar_helper(bridge_channel->chan, "CONFBRIDGE_RESULT", "TIMEOUT");
2101         return -1;
2102 }
2103
2104 static int conf_rec_name(struct confbridge_user *user, const char *conf_name)
2105 {
2106         char destdir[PATH_MAX];
2107         int res;
2108         int duration = 20;
2109
2110         snprintf(destdir, sizeof(destdir), "%s/confbridge", ast_config_AST_SPOOL_DIR);
2111
2112         if (ast_mkdir(destdir, 0777) != 0) {
2113                 ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", destdir, strerror(errno));
2114                 return -1;
2115         }
2116         snprintf(user->name_rec_location, sizeof(user->name_rec_location),
2117                  "%s/confbridge-name-%s-%s", destdir,
2118                  conf_name, ast_channel_uniqueid(user->chan));
2119
2120         if (!(ast_test_flag(&user->u_profile, USER_OPT_ANNOUNCE_JOIN_LEAVE_REVIEW))) {
2121                 res = ast_play_and_record(user->chan,
2122                         "vm-rec-name",
2123                         user->name_rec_location,
2124                         10,
2125                         "sln",
2126                         &duration,
2127                         NULL,
2128                         ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE),
2129                         0,
2130                         NULL);
2131         } else {
2132                 res = ast_record_review(user->chan,
2133                         "vm-rec-name",
2134                         user->name_rec_location,
2135                         10,
2136                         "sln",
2137                         &duration,
2138                         NULL);
2139         }
2140
2141         if (res == -1) {
2142                 user->name_rec_location[0] = '\0';
2143                 return -1;
2144         }
2145         return 0;
2146 }
2147
2148 static int join_callback(struct ast_bridge_channel *bridge_channel, void *ignore)
2149 {
2150         async_play_sound_ready(bridge_channel->chan);
2151         return 0;
2152 }
2153
2154 /*! \brief The ConfBridge application */
2155 static int confbridge_exec(struct ast_channel *chan, const char *data)
2156 {
2157         int res = 0, volume_adjustments[2];
2158         int quiet = 0;
2159         char *parse;
2160         const char *b_profile_name = NULL;
2161         const char *u_profile_name = NULL;
2162         const char *menu_profile_name = NULL;
2163         struct confbridge_conference *conference = NULL;
2164         struct confbridge_user user = {
2165                 .chan = chan,
2166                 .tech_args.talking_threshold = DEFAULT_TALKING_THRESHOLD,
2167                 .tech_args.silence_threshold = DEFAULT_SILENCE_THRESHOLD,
2168                 .tech_args.drop_silence = 0,
2169         };
2170         AST_DECLARE_APP_ARGS(args,
2171                 AST_APP_ARG(conf_name);
2172                 AST_APP_ARG(b_profile_name);
2173                 AST_APP_ARG(u_profile_name);
2174                 AST_APP_ARG(menu_profile_name);
2175         );
2176
2177         if (ast_channel_state(chan) != AST_STATE_UP) {
2178                 ast_answer(chan);
2179         }
2180
2181         if (ast_bridge_features_init(&user.features)) {
2182                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2183                 res = -1;
2184                 goto confbridge_cleanup;
2185         }
2186
2187         /* We need to make a copy of the input string if we are going to modify it! */
2188         parse = ast_strdupa(data);
2189
2190         AST_STANDARD_APP_ARGS(args, parse);
2191
2192         if (ast_strlen_zero(args.conf_name)) {
2193                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2194                 ast_log(LOG_WARNING, "%s requires an argument (conference name[,options])\n", app);
2195                 res = -1;
2196                 goto confbridge_cleanup;
2197         }
2198
2199         if (strlen(args.conf_name) >= MAX_CONF_NAME) {
2200                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2201                 ast_log(LOG_WARNING, "%s does not accept conference names longer than %d\n", app, MAX_CONF_NAME - 1);
2202                 res = -1;
2203                 goto confbridge_cleanup;
2204         }
2205
2206         /* bridge profile name */
2207         if (args.argc > 1 && !ast_strlen_zero(args.b_profile_name)) {
2208                 b_profile_name = args.b_profile_name;
2209         }
2210         if (!conf_find_bridge_profile(chan, b_profile_name, &user.b_profile)) {
2211                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2212                 ast_log(LOG_WARNING, "Conference bridge profile %s does not exist\n", b_profile_name ?
2213                         b_profile_name : DEFAULT_BRIDGE_PROFILE);
2214                 res = -1;
2215                 goto confbridge_cleanup;
2216         }
2217
2218         /* user profile name */
2219         if (args.argc > 2 && !ast_strlen_zero(args.u_profile_name)) {
2220                 u_profile_name = args.u_profile_name;
2221         }
2222         if (!conf_find_user_profile(chan, u_profile_name, &user.u_profile)) {
2223                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2224                 ast_log(LOG_WARNING, "Conference user profile %s does not exist\n", u_profile_name ?
2225                         u_profile_name : DEFAULT_USER_PROFILE);
2226                 res = -1;
2227                 goto confbridge_cleanup;
2228         }
2229
2230         quiet = ast_test_flag(&user.u_profile, USER_OPT_QUIET);
2231
2232         /* ask for a PIN immediately after finding user profile.  This has to be
2233          * prompted for requardless of quiet setting. */
2234         if (!ast_strlen_zero(user.u_profile.pin)) {
2235                 if (conf_get_pin(chan, &user)) {
2236                         pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2237                         res = -1; /* invalid PIN */
2238                         goto confbridge_cleanup;
2239                 }
2240         }
2241
2242         /* See if we need them to record a intro name */
2243         if (!quiet &&
2244                 (ast_test_flag(&user.u_profile, USER_OPT_ANNOUNCE_JOIN_LEAVE) ||
2245                 (ast_test_flag(&user.u_profile, USER_OPT_ANNOUNCE_JOIN_LEAVE_REVIEW)))) {
2246                 conf_rec_name(&user, args.conf_name);
2247         }
2248
2249         /* menu name */
2250         if (args.argc > 3 && !ast_strlen_zero(args.menu_profile_name)) {
2251                 menu_profile_name = args.menu_profile_name;
2252         }
2253
2254         if (conf_set_menu_to_user(chan, &user, menu_profile_name)) {
2255                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2256                 ast_log(LOG_WARNING, "Conference menu profile %s does not exist\n", menu_profile_name ?
2257                         menu_profile_name : DEFAULT_MENU_PROFILE);
2258                 res = -1;
2259                 goto confbridge_cleanup;
2260         }
2261
2262         /* Set if DTMF should pass through for this user or not */
2263         if (ast_test_flag(&user.u_profile, USER_OPT_DTMF_PASS)) {
2264                 user.features.dtmf_passthrough = 1;
2265         } else {
2266                 user.features.dtmf_passthrough = 0;
2267         }
2268
2269         /* Set dsp threshold values if present */
2270         if (user.u_profile.talking_threshold) {
2271                 user.tech_args.talking_threshold = user.u_profile.talking_threshold;
2272         }
2273         if (user.u_profile.silence_threshold) {
2274                 user.tech_args.silence_threshold = user.u_profile.silence_threshold;
2275         }
2276
2277         /* Set a talker indicate call back if talking detection is requested */
2278         if (ast_test_flag(&user.u_profile, USER_OPT_TALKER_DETECT)) {
2279                 if (ast_bridge_talk_detector_hook(&user.features, conf_handle_talker_cb,
2280                         &user, NULL, AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
2281                         pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2282                         res = -1;
2283                         goto confbridge_cleanup;
2284                 }
2285         }
2286
2287         /* Look for a conference bridge matching the provided name */
2288         if (!(conference = join_conference_bridge(args.conf_name, &user))) {
2289                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2290                 res = -1;
2291                 goto confbridge_cleanup;
2292         }
2293
2294         /* Keep a copy of volume adjustments so we can restore them later if need be */
2295         volume_adjustments[0] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_READ);
2296         volume_adjustments[1] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_WRITE);
2297
2298         if (ast_test_flag(&user.u_profile, USER_OPT_DROP_SILENCE)) {
2299                 user.tech_args.drop_silence = 1;
2300         }
2301
2302         if (ast_test_flag(&user.u_profile, USER_OPT_JITTERBUFFER)) {
2303                 char *func_jb;
2304                 if ((func_jb = ast_module_helper("", "func_jitterbuffer", 0, 0, 0, 0))) {
2305                         ast_free(func_jb);
2306                         ast_func_write(chan, "JITTERBUFFER(adaptive)", "default");
2307                 }
2308         }
2309
2310         if (ast_test_flag(&user.u_profile, USER_OPT_DENOISE)) {
2311                 char *mod_speex;
2312                 /* Reduce background noise from each participant */
2313                 if ((mod_speex = ast_module_helper("", "codec_speex", 0, 0, 0, 0))) {
2314                         ast_free(mod_speex);
2315                         ast_func_write(chan, "DENOISE(rx)", "on");
2316                 }
2317         }
2318
2319         /* if this user has a intro, play it before entering */
2320         if (!ast_strlen_zero(user.name_rec_location)) {
2321                 ast_autoservice_start(chan);
2322                 play_sound_file(conference, user.name_rec_location);
2323                 play_sound_file(conference,
2324                         conf_get_sound(CONF_SOUND_HAS_JOINED, conference->b_profile.sounds));
2325                 ast_autoservice_stop(chan);
2326         }
2327
2328         /* Play the Join sound to both the conference and the user entering. */
2329         if (!quiet) {
2330                 const char *join_sound = conf_get_sound(CONF_SOUND_JOIN, conference->b_profile.sounds);
2331
2332                 if (strcmp(conference->b_profile.language, ast_channel_language(chan))) {
2333                         ast_stream_and_wait(chan, join_sound, "");
2334                         ast_autoservice_start(chan);
2335                         play_sound_file(conference, join_sound);
2336                         ast_autoservice_stop(chan);
2337                 } else {
2338                         async_play_sound_file(conference, join_sound, chan);
2339                 }
2340         }
2341
2342         if (user.u_profile.timeout) {
2343                 ast_bridge_interval_hook(&user.features,
2344                         0,
2345                         user.u_profile.timeout * 1000,
2346                         user_timeout,
2347                         NULL,
2348                         NULL,
2349                         AST_BRIDGE_HOOK_REMOVE_ON_PULL);
2350         }
2351
2352         /* See if we need to automatically set this user as a video source or not */
2353         handle_video_on_join(conference, user.chan, ast_test_flag(&user.u_profile, USER_OPT_MARKEDUSER));
2354
2355         conf_moh_unsuspend(&user);
2356
2357         /* Join our conference bridge for real */
2358         send_join_event(&user, conference);
2359
2360         if (ast_bridge_join_hook(&user.features, join_callback, NULL, NULL, 0)) {
2361                 async_play_sound_ready(user.chan);
2362         }
2363
2364         ast_bridge_join(conference->bridge,
2365                 chan,
2366                 NULL,
2367                 &user.features,
2368                 &user.tech_args,
2369                 0);
2370
2371         /* This is a catch-all in case joining the bridge failed or for some reason
2372          * an async announcement got queued up and hasn't been told to play yet
2373          */
2374         async_play_sound_ready(chan);
2375
2376         if (!user.kicked && ast_check_hangup(chan)) {
2377                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "HANGUP");
2378         }
2379
2380         send_leave_event(&user, conference);
2381
2382         /* if we're shutting down, don't attempt to do further processing */
2383         if (ast_shutting_down()) {
2384                 /*
2385                  * Not taking any new calls at this time.  We cannot create
2386                  * the announcer channel if this is the first channel into
2387                  * the conference and we certainly cannot create any
2388                  * recording channel.
2389                  */
2390                 leave_conference(&user);
2391                 conference = NULL;
2392                 goto confbridge_cleanup;
2393         }
2394
2395         /* If this user was a video source, we need to clean up and possibly pick a new source. */
2396         handle_video_on_exit(conference, user.chan);
2397
2398         /* if this user has a intro, play it when leaving */
2399         if (!quiet && !ast_strlen_zero(user.name_rec_location)) {
2400                 async_play_sound_file(conference, user.name_rec_location, NULL);
2401                 async_play_sound_file(conference,
2402                         conf_get_sound(CONF_SOUND_HAS_LEFT, conference->b_profile.sounds), NULL);
2403         }
2404
2405         /* play the leave sound */
2406         if (!quiet) {
2407                 const char *leave_sound = conf_get_sound(CONF_SOUND_LEAVE, conference->b_profile.sounds);
2408                 async_play_sound_file(conference, leave_sound, NULL);
2409         }
2410
2411         /* If the user was kicked from the conference play back the audio prompt for it */
2412         if (!quiet && user.kicked) {
2413                 res = ast_stream_and_wait(chan,
2414                         conf_get_sound(CONF_SOUND_KICKED, conference->b_profile.sounds),
2415                         "");
2416         }
2417
2418         /* Easy as pie, depart this channel from the conference bridge */
2419         leave_conference(&user);
2420         conference = NULL;
2421
2422         /* Restore volume adjustments to previous values in case they were changed */
2423         if (volume_adjustments[0]) {
2424                 ast_audiohook_volume_set(chan, AST_AUDIOHOOK_DIRECTION_READ, volume_adjustments[0]);
2425         }
2426         if (volume_adjustments[1]) {
2427                 ast_audiohook_volume_set(chan, AST_AUDIOHOOK_DIRECTION_WRITE, volume_adjustments[1]);
2428         }
2429
2430         if (!ast_strlen_zero(user.name_rec_location)) {
2431                 ast_filedelete(user.name_rec_location, NULL);
2432         }
2433
2434 confbridge_cleanup:
2435         ast_bridge_features_cleanup(&user.features);
2436         conf_bridge_profile_destroy(&user.b_profile);
2437         return res;
2438 }
2439
2440 static int action_toggle_mute(struct confbridge_conference *conference,
2441                               struct confbridge_user *user,
2442                               struct ast_bridge_channel *bridge_channel)
2443 {
2444         int mute;
2445
2446         /* Toggle user level mute request. */
2447         mute = !user->muted;
2448         generic_mute_unmute_user(conference, user, mute);
2449
2450         return play_file(bridge_channel, NULL,
2451                 conf_get_sound(mute ? CONF_SOUND_MUTED : CONF_SOUND_UNMUTED,
2452                         conference->b_profile.sounds)) < 0;
2453 }
2454
2455 static int action_toggle_mute_participants(struct confbridge_conference *conference, struct confbridge_user *user)
2456 {
2457         struct confbridge_user *cur_user = NULL;
2458         const char *sound_to_play;
2459         int mute;
2460
2461         ao2_lock(conference);
2462
2463         /* Toggle bridge level mute request. */
2464         mute = !conference->muted;
2465         conference->muted = mute;
2466
2467         AST_LIST_TRAVERSE(&conference->active_list, cur_user, list) {
2468                 if (!ast_test_flag(&cur_user->u_profile, USER_OPT_ADMIN)) {
2469                         /* Set user level to bridge level mute request. */
2470                         cur_user->muted = mute;
2471                         conf_update_user_mute(cur_user);
2472                 }
2473         }
2474
2475         ao2_unlock(conference);
2476
2477         sound_to_play = conf_get_sound(
2478                 mute ? CONF_SOUND_PARTICIPANTS_MUTED : CONF_SOUND_PARTICIPANTS_UNMUTED,
2479                 conference->b_profile.sounds);
2480
2481         if (strcmp(conference->b_profile.language, ast_channel_language(user->chan))) {
2482                 /* The host needs to hear it seperately, as they don't get the audio from play_sound_helper */
2483                 ast_stream_and_wait(user->chan, sound_to_play, "");
2484
2485                 /* Announce to the group that all participants are muted */
2486                 ast_autoservice_start(user->chan);
2487                 play_sound_file(conference, sound_to_play);
2488                 ast_autoservice_stop(user->chan);
2489         } else {
2490                 /* Playing the sound asynchronously lets the sound be heard by everyone at once */
2491                 async_play_sound_file(conference, sound_to_play, user->chan);
2492         }
2493
2494         return 0;
2495 }
2496
2497 static int action_playback(struct ast_bridge_channel *bridge_channel, const char *playback_file)
2498 {
2499         char *file_copy = ast_strdupa(playback_file);
2500         char *file = NULL;
2501
2502         while ((file = strsep(&file_copy, "&"))) {
2503                 if (ast_stream_and_wait(bridge_channel->chan, file, "")) {
2504                         ast_log(LOG_WARNING, "Failed to playback file %s to channel\n", file);
2505                         return -1;
2506                 }
2507         }
2508         return 0;
2509 }
2510
2511 static int action_playback_and_continue(struct confbridge_conference *conference,
2512         struct confbridge_user *user,
2513         struct ast_bridge_channel *bridge_channel,
2514         struct conf_menu *menu,
2515         const char *playback_file,
2516         const char *cur_dtmf,
2517         int *stop_prompts)
2518 {
2519         int i;
2520         int digit = 0;
2521         char dtmf[MAXIMUM_DTMF_FEATURE_STRING];
2522         struct conf_menu_entry new_menu_entry = { { 0, }, };
2523         char *file_copy = ast_strdupa(playback_file);
2524         char *file = NULL;
2525
2526         while ((file = strsep(&file_copy, "&"))) {
2527                 if (ast_streamfile(bridge_channel->chan, file, ast_channel_language(bridge_channel->chan))) {
2528                         ast_log(LOG_WARNING, "Failed to playback file %s to channel\n", file);
2529                         return -1;
2530                 }
2531
2532                 /* now wait for more digits. */
2533                 if (!(digit = ast_waitstream(bridge_channel->chan, AST_DIGIT_ANY))) {
2534                         /* streaming finished and no DTMF was entered */
2535                         continue;
2536                 } else if (digit == -1) {
2537                         /* error */
2538                         return -1;
2539                 } else {
2540                         break; /* dtmf was entered */
2541                 }
2542         }
2543         if (!digit) {
2544                 /* streaming finished on all files and no DTMF was entered */
2545                 return -1;
2546         }
2547         ast_stopstream(bridge_channel->chan);
2548
2549         /* If we get here, then DTMF has been entered, This means no
2550          * additional prompts should be played for this menu entry */
2551         *stop_prompts = 1;
2552
2553         /* If a digit was pressed during the payback, update
2554          * the dtmf string and look for a new menu entry in the
2555          * menu structure */
2556         ast_copy_string(dtmf, cur_dtmf, sizeof(dtmf));
2557         for (i = 0; i < (MAXIMUM_DTMF_FEATURE_STRING - 1); i++) {
2558                 dtmf[i] = cur_dtmf[i];
2559                 if (!dtmf[i]) {
2560                         dtmf[i] = (char) digit;
2561                         dtmf[i + 1] = '\0';
2562                         i = -1;
2563                         break;
2564                 }
2565         }
2566         /* If i is not -1 then the new dtmf digit was _NOT_ added to the string.
2567          * If this is the case, no new DTMF sequence should be looked for. */
2568         if (i != -1) {
2569                 return 0;
2570         }
2571
2572         if (conf_find_menu_entry_by_sequence(dtmf, menu, &new_menu_entry)) {
2573                 execute_menu_entry(conference,
2574                         user,
2575                         bridge_channel,
2576                         &new_menu_entry, menu);
2577                 conf_menu_entry_destroy(&new_menu_entry);
2578         }
2579         return 0;
2580 }
2581
2582 static int action_kick_last(struct confbridge_conference *conference,
2583         struct ast_bridge_channel *bridge_channel,
2584         struct confbridge_user *user)
2585 {
2586         struct confbridge_user *last_user = NULL;
2587         int isadmin = ast_test_flag(&user->u_profile, USER_OPT_ADMIN);
2588
2589         if (!isadmin) {
2590                 play_file(bridge_channel, NULL,
2591                         conf_get_sound(CONF_SOUND_ERROR_MENU, conference->b_profile.sounds));
2592                 ast_log(LOG_WARNING, "Only admin users can use the kick_last menu action. Channel %s of conf %s is not an admin.\n",
2593                         ast_channel_name(bridge_channel->chan),
2594                         conference->name);
2595                 return -1;
2596         }
2597
2598         ao2_lock(conference);
2599         if (((last_user = AST_LIST_LAST(&conference->active_list)) == user)
2600                 || (ast_test_flag(&last_user->u_profile, USER_OPT_ADMIN))) {
2601                 ao2_unlock(conference);
2602                 play_file(bridge_channel, NULL,
2603                         conf_get_sound(CONF_SOUND_ERROR_MENU, conference->b_profile.sounds));
2604         } else if (last_user && !last_user->kicked) {
2605                 last_user->kicked = 1;
2606                 pbx_builtin_setvar_helper(last_user->chan, "CONFBRIDGE_RESULT", "KICKED");
2607                 ast_bridge_remove(conference->bridge, last_user->chan);
2608                 ao2_unlock(conference);
2609         }
2610         return 0;
2611 }
2612
2613 static int action_dialplan_exec(struct ast_bridge_channel *bridge_channel, struct conf_menu_action *menu_action)
2614 {
2615         struct ast_pbx_args args;
2616         struct ast_pbx *pbx;
2617         char *exten;
2618         char *context;
2619         int priority;
2620         int res;
2621
2622         memset(&args, 0, sizeof(args));
2623         args.no_hangup_chan = 1;
2624
2625         ast_channel_lock(bridge_channel->chan);
2626
2627         /*save off*/
2628         exten = ast_strdupa(ast_channel_exten(bridge_channel->chan));
2629         context = ast_strdupa(ast_channel_context(bridge_channel->chan));
2630         priority = ast_channel_priority(bridge_channel->chan);
2631         pbx = ast_channel_pbx(bridge_channel->chan);
2632         ast_channel_pbx_set(bridge_channel->chan, NULL);
2633
2634         /*set new*/
2635         ast_channel_exten_set(bridge_channel->chan, menu_action->data.dialplan_args.exten);
2636         ast_channel_context_set(bridge_channel->chan, menu_action->data.dialplan_args.context);
2637         ast_channel_priority_set(bridge_channel->chan, menu_action->data.dialplan_args.priority);
2638
2639         ast_channel_unlock(bridge_channel->chan);
2640
2641         /*execute*/
2642         res = ast_pbx_run_args(bridge_channel->chan, &args);
2643
2644         /*restore*/
2645         ast_channel_lock(bridge_channel->chan);
2646
2647         ast_channel_exten_set(bridge_channel->chan, exten);
2648         ast_channel_context_set(bridge_channel->chan, context);
2649         ast_channel_priority_set(bridge_channel->chan, priority);
2650         ast_channel_pbx_set(bridge_channel->chan, pbx);
2651
2652         ast_channel_unlock(bridge_channel->chan);
2653
2654         return res;
2655 }
2656
2657 static int execute_menu_entry(struct confbridge_conference *conference,
2658         struct confbridge_user *user,
2659         struct ast_bridge_channel *bridge_channel,
2660         struct conf_menu_entry *menu_entry,
2661         struct conf_menu *menu)
2662 {
2663         struct conf_menu_action *menu_action;
2664         int isadmin = ast_test_flag(&user->u_profile, USER_OPT_ADMIN);
2665         int stop_prompts = 0;
2666         int res = 0;
2667
2668         AST_LIST_TRAVERSE(&menu_entry->actions, menu_action, action) {
2669                 switch (menu_action->id) {
2670                 case MENU_ACTION_TOGGLE_MUTE:
2671                         res |= action_toggle_mute(conference, user, bridge_channel);
2672                         break;
2673                 case MENU_ACTION_ADMIN_TOGGLE_MUTE_PARTICIPANTS:
2674                         if (!isadmin) {
2675                                 break;
2676                         }
2677                         action_toggle_mute_participants(conference, user);
2678                         break;
2679                 case MENU_ACTION_PARTICIPANT_COUNT:
2680                         announce_user_count(conference, user, bridge_channel);
2681                         break;
2682                 case MENU_ACTION_PLAYBACK:
2683                         if (!stop_prompts) {
2684                                 res |= action_playback(bridge_channel, menu_action->data.playback_file);
2685                                 ast_test_suite_event_notify("CONF_MENU_PLAYBACK",
2686                                         "Message: %s\r\nChannel: %s",
2687                                         menu_action->data.playback_file, ast_channel_name(bridge_channel->chan));
2688                         }
2689                         break;
2690                 case MENU_ACTION_RESET_LISTENING:
2691                         ast_audiohook_volume_set(user->chan, AST_AUDIOHOOK_DIRECTION_WRITE, 0);
2692                         break;
2693                 case MENU_ACTION_RESET_TALKING:
2694                         ast_audiohook_volume_set(user->chan, AST_AUDIOHOOK_DIRECTION_READ, 0);
2695                         break;
2696                 case MENU_ACTION_INCREASE_LISTENING:
2697                         ast_audiohook_volume_adjust(user->chan,
2698                                 AST_AUDIOHOOK_DIRECTION_WRITE, 1);
2699                         break;
2700                 case MENU_ACTION_DECREASE_LISTENING:
2701                         ast_audiohook_volume_adjust(user->chan,
2702                                 AST_AUDIOHOOK_DIRECTION_WRITE, -1);
2703                         break;
2704                 case MENU_ACTION_INCREASE_TALKING:
2705                         ast_audiohook_volume_adjust(user->chan,
2706                                 AST_AUDIOHOOK_DIRECTION_READ, 1);
2707                         break;
2708                 case MENU_ACTION_DECREASE_TALKING:
2709                         ast_audiohook_volume_adjust(user->chan,
2710                                 AST_AUDIOHOOK_DIRECTION_READ, -1);
2711                         break;
2712                 case MENU_ACTION_PLAYBACK_AND_CONTINUE:
2713                         if (!(stop_prompts)) {
2714                                 res |= action_playback_and_continue(conference,
2715                                         user,
2716                                         bridge_channel,
2717                                         menu,
2718                                         menu_action->data.playback_file,
2719                                         menu_entry->dtmf,
2720                                         &stop_prompts);
2721                         }
2722                         break;
2723                 case MENU_ACTION_DIALPLAN_EXEC:
2724                         res |= action_dialplan_exec(bridge_channel, menu_action);
2725                         break;
2726                 case MENU_ACTION_ADMIN_TOGGLE_LOCK:
2727                         if (!isadmin) {
2728                                 break;
2729                         }
2730                         conference->locked = (!conference->locked ? 1 : 0);
2731                         res |= play_file(bridge_channel, NULL,
2732                                 conf_get_sound(
2733                                         conference->locked ? CONF_SOUND_LOCKED_NOW : CONF_SOUND_UNLOCKED_NOW,
2734                                         conference->b_profile.sounds)) < 0;
2735                         break;
2736                 case MENU_ACTION_ADMIN_KICK_LAST:
2737                         res |= action_kick_last(conference, bridge_channel, user);
2738                         break;
2739                 case MENU_ACTION_LEAVE:
2740                         pbx_builtin_setvar_helper(bridge_channel->chan, "CONFBRIDGE_RESULT", "DTMF");
2741                         ao2_lock(conference);
2742                         ast_bridge_remove(conference->bridge, bridge_channel->chan);
2743                         ast_test_suite_event_notify("CONF_MENU_LEAVE",
2744                                 "Channel: %s",
2745                                 ast_channel_name(bridge_channel->chan));
2746                         ao2_unlock(conference);
2747                         break;
2748                 case MENU_ACTION_NOOP:
2749                         break;
2750                 case MENU_ACTION_SET_SINGLE_VIDEO_SRC:
2751                         ao2_lock(conference);
2752                         ast_bridge_set_single_src_video_mode(conference->bridge, bridge_channel->chan);
2753                         ao2_unlock(conference);
2754                         break;
2755                 case MENU_ACTION_RELEASE_SINGLE_VIDEO_SRC:
2756                         handle_video_on_exit(conference, bridge_channel->chan);
2757                         break;
2758                 }
2759         }
2760         return res;
2761 }
2762
2763 int conf_handle_dtmf(struct ast_bridge_channel *bridge_channel,
2764         struct confbridge_user *user,
2765         struct conf_menu_entry *menu_entry,
2766         struct conf_menu *menu)
2767 {
2768         /* See if music on hold is playing */
2769         conf_moh_suspend(user);
2770
2771         /* execute the list of actions associated with this menu entry */
2772         execute_menu_entry(user->conference, user, bridge_channel, menu_entry, menu);
2773
2774         /* See if music on hold needs to be started back up again */
2775         conf_moh_unsuspend(user);
2776
2777         async_play_sound_ready(bridge_channel->chan);
2778
2779         return 0;
2780 }
2781
2782 static int kick_conference_participant(struct confbridge_conference *conference,
2783         const char *channel)
2784 {
2785         int res = -1;
2786         int match;
2787         struct confbridge_user *user = NULL;
2788         int all = !strcasecmp("all", channel);
2789         int participants = !strcasecmp("participants", channel);
2790
2791         SCOPED_AO2LOCK(bridge_lock, conference);
2792
2793         AST_LIST_TRAVERSE(&conference->active_list, user, list) {
2794                 if (user->kicked) {
2795                         continue;
2796                 }
2797                 match = !strcasecmp(channel, ast_channel_name(user->chan));
2798                 if (match || all
2799                                 || (participants && !ast_test_flag(&user->u_profile, USER_OPT_ADMIN))) {
2800                         user->kicked = 1;
2801                         pbx_builtin_setvar_helper(user->chan, "CONFBRIDGE_RESULT", "KICKED");
2802                         ast_bridge_remove(conference->bridge, user->chan);
2803                         res = 0;
2804                         if (match) {
2805                                 return res;
2806                         }
2807                 }
2808         }
2809         AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
2810                 if (user->kicked) {
2811                         continue;
2812                 }
2813                 match = !strcasecmp(channel, ast_channel_name(user->chan));
2814                 if (match || all
2815                                 || (participants && !ast_test_flag(&user->u_profile, USER_OPT_ADMIN))) {
2816                         user->kicked = 1;
2817                         pbx_builtin_setvar_helper(user->chan, "CONFBRIDGE_RESULT", "KICKED");
2818                         ast_bridge_remove(conference->bridge, user->chan);
2819                         res = 0;
2820                         if (match) {
2821                                 return res;
2822                         }
2823                 }
2824         }
2825
2826         return res;
2827 }
2828
2829 static char *complete_confbridge_name(const char *line, const char *word, int pos, int state)
2830 {
2831         int which = 0;
2832         struct confbridge_conference *conference;
2833         char *res = NULL;
2834         int wordlen = strlen(word);
2835         struct ao2_iterator iter;
2836
2837         iter = ao2_iterator_init(conference_bridges, 0);
2838         while ((conference = ao2_iterator_next(&iter))) {
2839                 if (!strncasecmp(conference->name, word, wordlen) && ++which > state) {
2840                         res = ast_strdup(conference->name);
2841                         ao2_ref(conference, -1);
2842                         break;
2843                 }
2844                 ao2_ref(conference, -1);
2845         }
2846         ao2_iterator_destroy(&iter);
2847
2848         return res;
2849 }
2850
2851 static char *complete_confbridge_participant(const char *conference_name, const char *line, const char *word, int pos, int state)
2852 {
2853         int which = 0;
2854         RAII_VAR(struct confbridge_conference *, conference, NULL, ao2_cleanup);
2855         struct confbridge_user *user;
2856         char *res = NULL;
2857         int wordlen = strlen(word);
2858
2859         conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
2860         if (!conference) {
2861                 return NULL;
2862         }
2863
2864         if (!strncasecmp("all", word, wordlen) && ++which > state) {
2865                 return ast_strdup("all");
2866         }
2867
2868         if (!strncasecmp("participants", word, wordlen) && ++which > state) {
2869                 return ast_strdup("participants");
2870         }
2871
2872         {
2873                 SCOPED_AO2LOCK(bridge_lock, conference);
2874                 AST_LIST_TRAVERSE(&conference->active_list, user, list) {
2875                         if (!strncasecmp(ast_channel_name(user->chan), word, wordlen) && ++which > state) {
2876                                 res = ast_strdup(ast_channel_name(user->chan));
2877                                 return res;
2878                         }
2879                 }
2880                 AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
2881                         if (!strncasecmp(ast_channel_name(user->chan), word, wordlen) && ++which > state) {
2882                                 res = ast_strdup(ast_channel_name(user->chan));
2883                                 return res;
2884                         }
2885                 }
2886         }
2887
2888         return NULL;
2889 }
2890
2891 static char *handle_cli_confbridge_kick(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2892 {
2893         struct confbridge_conference *conference;
2894         int not_found;
2895
2896         switch (cmd) {
2897         case CLI_INIT:
2898                 e->command = "confbridge kick";
2899                 e->usage =
2900                         "Usage: confbridge kick <conference> <channel>\n"
2901                         "       Kicks a channel out of the conference bridge.\n"
2902                         "             (all to kick everyone, participants to kick non-admins).\n";
2903                 return NULL;
2904         case CLI_GENERATE:
2905                 if (a->pos == 2) {
2906                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
2907                 }
2908                 if (a->pos == 3) {
2909                         return complete_confbridge_participant(a->argv[2], a->line, a->word, a->pos, a->n);
2910                 }
2911                 return NULL;
2912         }
2913
2914         if (a->argc != 4) {
2915                 return CLI_SHOWUSAGE;
2916         }
2917
2918         conference = ao2_find(conference_bridges, a->argv[2], OBJ_KEY);
2919         if (!conference) {
2920                 ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
2921                 return CLI_SUCCESS;
2922         }
2923         not_found = kick_conference_participant(conference, a->argv[3]);
2924         ao2_ref(conference, -1);
2925         if (not_found) {
2926                 if (!strcasecmp("all", a->argv[3]) || !strcasecmp("participants", a->argv[3])) {
2927                         ast_cli(a->fd, "No participants found!\n");
2928                 } else {
2929                         ast_cli(a->fd, "No participant named '%s' found!\n", a->argv[3]);
2930                 }
2931                 return CLI_SUCCESS;
2932         }
2933         ast_cli(a->fd, "Kicked '%s' out of conference '%s'\n", a->argv[3], a->argv[2]);
2934         return CLI_SUCCESS;
2935 }
2936
2937 static void handle_cli_confbridge_list_item(struct ast_cli_args *a, struct confbridge_user *user, int waiting)
2938 {
2939         char flag_str[6 + 1];/* Max flags + terminator */
2940         int pos = 0;
2941
2942         /* Build flags column string. */
2943         if (ast_test_flag(&user->u_profile, USER_OPT_ADMIN)) {
2944                 flag_str[pos++] = 'A';
2945         }
2946         if (ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER)) {
2947                 flag_str[pos++] = 'M';
2948         }
2949         if (ast_test_flag(&user->u_profile, USER_OPT_WAITMARKED)) {
2950                 flag_str[pos++] = 'W';
2951         }
2952         if (ast_test_flag(&user->u_profile, USER_OPT_ENDMARKED)) {
2953                 flag_str[pos++] = 'E';
2954         }
2955         if (user->muted) {
2956                 flag_str[pos++] = 'm';
2957         }
2958         if (waiting) {
2959                 flag_str[pos++] = 'w';
2960         }
2961         flag_str[pos] = '\0';
2962
2963         ast_cli(a->fd, "%-30s %-6s %-16s %-16s %-16s %s\n",
2964                 ast_channel_name(user->chan),
2965                 flag_str,
2966                 user->u_profile.name,
2967                 user->conference->b_profile.name,
2968                 user->menu_name,
2969                 S_COR(ast_channel_caller(user->chan)->id.number.valid,
2970                         ast_channel_caller(user->chan)->id.number.str, "<unknown>"));
2971 }
2972
2973 static char *handle_cli_confbridge_list(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2974 {
2975         struct confbridge_conference *conference;
2976
2977         switch (cmd) {
2978         case CLI_INIT:
2979                 e->command = "confbridge list";
2980                 e->usage =
2981                         "Usage: confbridge list [<name>]\n"
2982                         "       Lists all currently active conference bridges or a specific conference bridge.\n"
2983                         "\n"
2984                         "       When a conference bridge name is provided, flags may be shown for users. Below\n"
2985                         "       are the flags and what they represent.\n"
2986                         "\n"
2987                         "       Flags:\n"
2988                         "         A - The user is an admin\n"
2989                         "         M - The user is a marked user\n"
2990                         "         W - The user must wait for a marked user to join\n"
2991                         "         E - The user will be kicked after the last marked user leaves the conference\n"
2992                         "         m - The user is muted\n"
2993                         "         w - The user is waiting for a marked user to join\n";
2994                 return NULL;
2995         case CLI_GENERATE:
2996                 if (a->pos == 2) {
2997                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
2998                 }
2999                 return NULL;
3000         }
3001
3002         if (a->argc == 2) {
3003                 struct ao2_iterator iter;
3004
3005                 ast_cli(a->fd, "Conference Bridge Name           Users  Marked Locked Muted\n");
3006                 ast_cli(a->fd, "================================ ====== ====== ====== =====\n");
3007                 iter = ao2_iterator_init(conference_bridges, 0);
3008                 while ((conference = ao2_iterator_next(&iter))) {
3009                         ast_cli(a->fd, "%-32s %6u %6u %-6s %s\n",
3010                                 conference->name,
3011                                 conference->activeusers + conference->waitingusers,
3012                                 conference->markedusers,
3013                                 AST_CLI_YESNO(conference->locked),
3014                                 AST_CLI_YESNO(conference->muted));
3015                         ao2_ref(conference, -1);
3016                 }
3017                 ao2_iterator_destroy(&iter);
3018                 return CLI_SUCCESS;
3019         }
3020
3021         if (a->argc == 3) {
3022                 struct confbridge_user *user;
3023
3024                 conference = ao2_find(conference_bridges, a->argv[2], OBJ_KEY);
3025                 if (!conference) {
3026                         ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
3027                         return CLI_SUCCESS;
3028                 }
3029                 ast_cli(a->fd, "Channel                        Flags  User Profile     Bridge Profile   Menu             CallerID\n");
3030                 ast_cli(a->fd, "============================== ====== ================ ================ ================ ================\n");
3031                 ao2_lock(conference);
3032                 AST_LIST_TRAVERSE(&conference->active_list, user, list) {
3033                         handle_cli_confbridge_list_item(a, user, 0);
3034                 }
3035                 AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
3036                         handle_cli_confbridge_list_item(a, user, 1);
3037                 }
3038                 ao2_unlock(conference);
3039                 ao2_ref(conference, -1);
3040                 return CLI_SUCCESS;
3041         }
3042
3043         return CLI_SHOWUSAGE;
3044 }
3045
3046 /* \internal
3047  * \brief finds a conference by name and locks/unlocks.
3048  *
3049  * \retval 0 success
3050  * \retval -1 conference not found
3051  */
3052 static int generic_lock_unlock_helper(int lock, const char *conference_name)
3053 {
3054         struct confbridge_conference *conference;
3055         int res = 0;
3056
3057         conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
3058         if (!conference) {
3059                 return -1;
3060         }
3061         ao2_lock(conference);
3062         conference->locked = lock;
3063         ast_test_suite_event_notify("CONF_LOCK", "Message: conference %s\r\nConference: %s", conference->locked ? "locked" : "unlocked", conference->b_profile.name);
3064         ao2_unlock(conference);
3065         ao2_ref(conference, -1);
3066
3067         return res;
3068 }
3069
3070 /* \internal
3071  * \brief finds a conference user by channel name and mutes/unmutes them.
3072  *
3073  * \retval 0 success
3074  * \retval -1 conference not found
3075  * \retval -2 user not found
3076  */
3077 static int generic_mute_unmute_helper(int mute, const char *conference_name,
3078         const char *chan_name)
3079 {
3080         RAII_VAR(struct confbridge_conference *, conference, NULL, ao2_cleanup);
3081         struct confbridge_user *user;
3082         int all = !strcasecmp("all", chan_name);
3083         int participants = !strcasecmp("participants", chan_name);
3084         int res = -2;
3085
3086         conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
3087         if (!conference) {
3088                 return -1;
3089         }
3090
3091         {
3092                 SCOPED_AO2LOCK(bridge_lock, conference);
3093                 AST_LIST_TRAVERSE(&conference->active_list, user, list) {
3094                         int match = !strncasecmp(chan_name, ast_channel_name(user->chan),
3095                                 strlen(chan_name));
3096                         if (match || all
3097                                 || (participants && !ast_test_flag(&user->u_profile, USER_OPT_ADMIN))) {
3098                                 generic_mute_unmute_user(conference, user, mute);
3099                                 res = 0;
3100                                 if (match) {
3101                                         return res;
3102                                 }
3103                         }
3104                 }
3105
3106                 AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
3107                         int match = !strncasecmp(chan_name, ast_channel_name(user->chan),
3108                                 strlen(chan_name));
3109                         if (match || all
3110                                 || (participants && !ast_test_flag(&user->u_profile, USER_OPT_ADMIN))) {
3111                                 generic_mute_unmute_user(conference, user, mute);
3112                                 res = 0;
3113                                 if (match) {
3114                                         return res;
3115                                 }
3116                         }
3117                 }
3118         }
3119
3120         return res;
3121 }
3122
3123 static int cli_mute_unmute_helper(int mute, struct ast_cli_args *a)
3124 {
3125         int res = generic_mute_unmute_helper(mute, a->argv[2], a->argv[3]);
3126
3127         if (res == -1) {
3128                 ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
3129                 return -1;
3130         } else if (res == -2) {
3131                 if (!strcasecmp("all", a->argv[3]) || !strcasecmp("participants", a->argv[3])) {
3132                         ast_cli(a->fd, "No participants found in conference %s\n", a->argv[2]);
3133                 } else {
3134                         ast_cli(a->fd, "No channel named '%s' found in conference %s\n", a->argv[3], a->argv[2]);
3135                 }
3136                 return -1;
3137         }
3138         ast_cli(a->fd, "%s %s from confbridge %s\n", mute ? "Muting" : "Unmuting", a->argv[3], a->argv[2]);
3139         return 0;
3140 }
3141
3142 static char *handle_cli_confbridge_mute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3143 {
3144         switch (cmd) {
3145         case CLI_INIT:
3146                 e->command = "confbridge mute";
3147                 e->usage =
3148                         "Usage: confbridge mute <conference> <channel>\n"
3149                         "       Mute a channel in a conference.\n"
3150                         "              (all to mute everyone, participants to mute non-admins)\n"
3151                         "       If the specified channel is a prefix,\n"
3152                         "       the action will be taken on the first\n"
3153                     &n