d6229b93f65d600304cb5eca8d6ac9d262a2fe3a
[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
1479                 if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER)) {
1480                         ast_bridge_set_talker_src_video_mode(conference->bridge);
1481                 }
1482
1483                 /* Link it into the conference bridges container */
1484                 if (!ao2_link(conference_bridges, conference)) {
1485                         ao2_ref(conference, -1);
1486                         ao2_unlock(conference_bridges);
1487                         ast_log(LOG_ERROR,
1488                                 "Conference '%s' could not be added to the conferences list.\n", conference_name);
1489                         return NULL;
1490                 }
1491
1492                 /* Set the initial state to EMPTY */
1493                 conference->state = CONF_STATE_EMPTY;
1494
1495                 if (alloc_playback_chan(conference)) {
1496                         ao2_unlink(conference_bridges, conference);
1497                         ao2_ref(conference, -1);
1498                         ao2_unlock(conference_bridges);
1499                         ast_log(LOG_ERROR, "Could not allocate announcer channel for conference '%s'\n", conference_name);
1500                         return NULL;
1501                 }
1502
1503                 if (ast_taskprocessor_push(conference->playback_queue, push_announcer, ao2_bump(conference))) {
1504                         ao2_unlink(conference_bridges, conference);
1505                         ao2_ref(conference, -1);
1506                         ao2_unlock(conference_bridges);
1507                         ast_log(LOG_ERROR, "Could not add announcer channel for conference '%s' bridge\n", conference_name);
1508                         return NULL;
1509                 }
1510
1511                 if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_RECORD_CONFERENCE)) {
1512                         ao2_lock(conference);
1513                         conf_start_record(conference);
1514                         ao2_unlock(conference);
1515                 }
1516
1517                 send_conf_start_event(conference);
1518
1519                 if (!ast_strlen_zero(conference->b_profile.regcontext)) {
1520                         if (!ast_exists_extension(NULL, conference->b_profile.regcontext, conference->name, 1, NULL)) {
1521                                 ast_add_extension(conference->b_profile.regcontext, 1, conference->name, 1, NULL, NULL, "Noop", NULL, NULL, "ConfBridge");
1522                         }
1523                 }
1524
1525                 ast_debug(1, "Created conference '%s' and linked to container.\n", conference_name);
1526         }
1527
1528         ao2_unlock(conference_bridges);
1529
1530         /* Setup conference bridge user parameters */
1531         user->conference = conference;
1532
1533         ao2_lock(conference);
1534
1535         /* Determine if the new user should join the conference muted. */
1536         if (ast_test_flag(&user->u_profile, USER_OPT_STARTMUTED)
1537                 || (!ast_test_flag(&user->u_profile, USER_OPT_ADMIN) && conference->muted)) {
1538                 /* Set user level mute request. */
1539                 user->muted = 1;
1540         }
1541
1542         /*
1543          * Suspend any MOH until the user actually joins the bridge of
1544          * the conference.  This way any pre-join file playback does not
1545          * need to worry about MOH.
1546          */
1547         user->suspended_moh = 1;
1548
1549         if (handle_conf_user_join(user)) {
1550                 /* Invalid event, nothing was done, so we don't want to process a leave. */
1551                 ao2_unlock(conference);
1552                 ao2_ref(conference, -1);
1553                 user->conference = NULL;
1554                 return NULL;
1555         }
1556
1557         if (ast_check_hangup(user->chan)) {
1558                 ao2_unlock(conference);
1559                 leave_conference(user);
1560                 return NULL;
1561         }
1562
1563         ao2_unlock(conference);
1564
1565         /* If an announcement is to be played play it */
1566         if (!ast_strlen_zero(user->u_profile.announcement)) {
1567                 if (play_prompt_to_user(user,
1568                         user->u_profile.announcement)) {
1569                         leave_conference(user);
1570                         return NULL;
1571                 }
1572         }
1573
1574         /* Announce number of users if need be */
1575         if (ast_test_flag(&user->u_profile, USER_OPT_ANNOUNCEUSERCOUNT)) {
1576                 if (announce_user_count(conference, user, NULL)) {
1577                         leave_conference(user);
1578                         return NULL;
1579                 }
1580         }
1581
1582         if (ast_test_flag(&user->u_profile, USER_OPT_ANNOUNCEUSERCOUNTALL) &&
1583                 (conference->activeusers > user->u_profile.announce_user_count_all_after)) {
1584                 int user_count_res;
1585
1586                 /*
1587                  * We have to autoservice the new user because he has not quite
1588                  * joined the conference yet.
1589                  */
1590                 ast_autoservice_start(user->chan);
1591                 user_count_res = announce_user_count(conference, NULL, NULL);
1592                 ast_autoservice_stop(user->chan);
1593                 if (user_count_res) {
1594                         leave_conference(user);
1595                         return NULL;
1596                 }
1597         }
1598
1599         /* Handle post-join actions */
1600         while ((action = AST_LIST_REMOVE_HEAD(&user->post_join_list, list))) {
1601                 action->func(user);
1602                 ast_free(action);
1603         }
1604
1605         return conference;
1606 }
1607
1608 /*!
1609  * \brief Leave a conference
1610  *
1611  * \param user The conference user
1612  */
1613 static void leave_conference(struct confbridge_user *user)
1614 {
1615         struct post_join_action *action;
1616
1617         ao2_lock(user->conference);
1618         handle_conf_user_leave(user);
1619         ao2_unlock(user->conference);
1620
1621         /* Discard any post-join actions */
1622         while ((action = AST_LIST_REMOVE_HEAD(&user->post_join_list, list))) {
1623                 ast_free(action);
1624         }
1625
1626         /* Done mucking with the conference, huzzah */
1627         ao2_ref(user->conference, -1);
1628         user->conference = NULL;
1629 }
1630
1631 static void playback_common(struct confbridge_conference *conference, const char *filename, int say_number)
1632 {
1633         /* Don't try to play if the playback channel has been hung up */
1634         if (!conference->playback_chan) {
1635                 return;
1636         }
1637
1638         ast_autoservice_stop(conference->playback_chan);
1639
1640         /* The channel is all under our control, in goes the prompt */
1641         if (!ast_strlen_zero(filename)) {
1642                 ast_stream_and_wait(conference->playback_chan, filename, "");
1643         } else if (say_number >= 0) {
1644                 ast_say_number(conference->playback_chan, say_number, "",
1645                         ast_channel_language(conference->playback_chan), NULL);
1646         }
1647
1648         ast_autoservice_start(conference->playback_chan);
1649 }
1650
1651 struct playback_task_data {
1652         struct confbridge_conference *conference;
1653         const char *filename;
1654         int say_number;
1655         int playback_finished;
1656         ast_mutex_t lock;
1657         ast_cond_t cond;
1658 };
1659
1660 /*!
1661  * \brief Play an announcement into a confbridge
1662  *
1663  * This runs in the playback queue taskprocessor. This ensures that
1664  * all playbacks are handled in sequence and do not play over top one
1665  * another.
1666  *
1667  * This task runs synchronously so there is no need for performing any
1668  * sort of cleanup on the input parameter.
1669  *
1670  * \param data A playback_task_data
1671  * \return 0
1672  */
1673 static int playback_task(void *data)
1674 {
1675         struct playback_task_data *ptd = data;
1676
1677         playback_common(ptd->conference, ptd->filename, ptd->say_number);
1678
1679         ast_mutex_lock(&ptd->lock);
1680         ptd->playback_finished = 1;
1681         ast_cond_signal(&ptd->cond);
1682         ast_mutex_unlock(&ptd->lock);
1683
1684         return 0;
1685 }
1686
1687 static void playback_task_data_init(struct playback_task_data *ptd, struct confbridge_conference *conference,
1688                 const char *filename, int say_number)
1689 {
1690         ast_mutex_init(&ptd->lock);
1691         ast_cond_init(&ptd->cond, NULL);
1692
1693         ptd->filename = filename;
1694         ptd->say_number = say_number;
1695         ptd->conference = conference;
1696         ptd->playback_finished = 0;
1697 }
1698
1699 static void playback_task_data_destroy(struct playback_task_data *ptd)
1700 {
1701         ast_mutex_destroy(&ptd->lock);
1702         ast_cond_destroy(&ptd->cond);
1703 }
1704
1705 static int play_sound_helper(struct confbridge_conference *conference, const char *filename, int say_number)
1706 {
1707         struct playback_task_data ptd;
1708
1709         /* Do not waste resources trying to play files that do not exist */
1710         if (ast_strlen_zero(filename)) {
1711                 if (say_number < 0) {
1712                         return 0;
1713                 }
1714         } else if (!sound_file_exists(filename)) {
1715                 return 0;
1716         }
1717
1718         playback_task_data_init(&ptd, conference, filename, say_number);
1719         if (ast_taskprocessor_push(conference->playback_queue, playback_task, &ptd)) {
1720                 if (!ast_strlen_zero(filename)) {
1721                         ast_log(LOG_WARNING, "Unable to play file '%s' to conference %s\n",
1722                                 filename, conference->name);
1723                 } else {
1724                         ast_log(LOG_WARNING, "Unable to say number '%d' to conference %s\n",
1725                                 say_number, conference->name);
1726                 }
1727                 playback_task_data_destroy(&ptd);
1728                 return -1;
1729         }
1730
1731         /* Wait for the playback to complete */
1732         ast_mutex_lock(&ptd.lock);
1733         while (!ptd.playback_finished) {
1734                 ast_cond_wait(&ptd.cond, &ptd.lock);
1735         }
1736         ast_mutex_unlock(&ptd.lock);
1737
1738         playback_task_data_destroy(&ptd);
1739
1740         return 0;
1741 }
1742
1743 int play_sound_file(struct confbridge_conference *conference, const char *filename)
1744 {
1745         return play_sound_helper(conference, filename, -1);
1746 }
1747
1748 struct async_playback_task_data {
1749         struct confbridge_conference *conference;
1750         int say_number;
1751         struct ast_channel *initiator;
1752         char filename[0];
1753 };
1754
1755 struct async_datastore_data {
1756         ast_mutex_t lock;
1757         ast_cond_t cond;
1758         int wait;
1759 };
1760
1761 static void async_datastore_data_destroy(void *data)
1762 {
1763         struct async_datastore_data *add = data;
1764
1765         ast_mutex_destroy(&add->lock);
1766         ast_cond_destroy(&add->cond);
1767
1768         ast_free(add);
1769 }
1770
1771 /*!
1772  * \brief Datastore used for timing of async announcement playback
1773  *
1774  * Announcements that are played to the entire conference can be played
1775  * asynchronously (i.e. The channel that queues the playback does not wait
1776  * for the playback to complete before continuing)
1777  *
1778  * The thing about async announcements is that the channel that queues the
1779  * announcement is either not in the bridge or is in some other way "occupied"
1780  * at the time the announcement is queued. Because of that, the initiator of
1781  * the announcement may enter after the announcement has already started,
1782  * resulting in the sound being "clipped".
1783  *
1784  * This datastore makes it so that the channel that queues the async announcement
1785  * can say "I'm ready now". This way the announcement does not start until the
1786  * initiator of the announcement is ready to hear the sound.
1787  */
1788 static struct ast_datastore_info async_datastore_info = {
1789         .type = "Confbridge async playback",
1790         .destroy = async_datastore_data_destroy,
1791 };
1792
1793 static struct async_datastore_data *async_datastore_data_alloc(void)
1794 {
1795         struct async_datastore_data *add;
1796
1797         add = ast_malloc(sizeof(*add));
1798         if (!add) {
1799                 return NULL;
1800         }
1801
1802         ast_mutex_init(&add->lock);
1803         ast_cond_init(&add->cond, NULL);
1804         add->wait = 1;
1805
1806         return add;
1807 }
1808
1809 /*!
1810  * \brief Prepare the async playback datastore
1811  *
1812  * This is done prior to queuing an async announcement. If the
1813  * datastore has not yet been created, it is allocated and initialized.
1814  * If it already exists, we set it to be in "waiting" mode.
1815  *
1816  * \param initiator The channel that is queuing the async playback
1817  * \retval 0 Success
1818  * \retval -1 Failure :(
1819  */
1820 static int setup_async_playback_datastore(struct ast_channel *initiator)
1821 {
1822         struct ast_datastore *async_datastore;
1823
1824         async_datastore = ast_channel_datastore_find(initiator, &async_datastore_info, NULL);
1825         if (async_datastore) {
1826                 struct async_datastore_data *add;
1827
1828                 add = async_datastore->data;
1829                 add->wait = 1;
1830
1831                 return 0;
1832         }
1833
1834         async_datastore = ast_datastore_alloc(&async_datastore_info, NULL);
1835         if (!async_datastore) {
1836                 return -1;
1837         }
1838
1839         async_datastore->data = async_datastore_data_alloc();
1840         if (!async_datastore->data) {
1841                 ast_datastore_free(async_datastore);
1842                 return -1;
1843         }
1844
1845         ast_channel_datastore_add(initiator, async_datastore);
1846         return 0;
1847 }
1848
1849 static struct async_playback_task_data *async_playback_task_data_alloc(
1850         struct confbridge_conference *conference, const char *filename, int say_number,
1851         struct ast_channel *initiator)
1852 {
1853         struct async_playback_task_data *aptd;
1854
1855         aptd = ast_malloc(sizeof(*aptd) + strlen(filename) + 1);
1856         if (!aptd) {
1857                 return NULL;
1858         }
1859
1860         /* Safe */
1861         strcpy(aptd->filename, filename);
1862         aptd->say_number = say_number;
1863
1864         /* You may think that we need to bump the conference refcount since we are pushing
1865          * this task to the taskprocessor.
1866          *
1867          * In this case, that actually causes a problem. The destructor for the conference
1868          * pushes a hangup task into the taskprocessor and waits for it to complete before
1869          * continuing. If the destructor gets called from a taskprocessor task, we're
1870          * deadlocked.
1871          *
1872          * So is there a risk of the conference being freed out from under us? No. Since
1873          * the destructor pushes a task into the taskprocessor and waits for it to complete,
1874          * the destructor cannot free the conference out from under us. No further tasks
1875          * can be queued onto the taskprocessor after the hangup since no channels are referencing
1876          * the conference at that point any more.
1877          */
1878         aptd->conference = conference;
1879
1880         aptd->initiator = initiator;
1881         if (initiator) {
1882                 ast_channel_ref(initiator);
1883                 ast_channel_lock(aptd->initiator);
1884                 /* We don't really care if this fails. If the datastore fails to get set up
1885                  * we'll still play the announcement. It's possible that the sound will be
1886                  * clipped for the initiator, but that's not the end of the world.
1887                  */
1888                 setup_async_playback_datastore(aptd->initiator);
1889                 ast_channel_unlock(aptd->initiator);
1890         }
1891
1892         return aptd;
1893 }
1894
1895 static void async_playback_task_data_destroy(struct async_playback_task_data *aptd)
1896 {
1897         ast_channel_cleanup(aptd->initiator);
1898         ast_free(aptd);
1899 }
1900
1901 /*!
1902  * \brief Wait for the initiator of an async playback to be ready
1903  *
1904  * See the description on the async_datastore_info structure for more
1905  * information about what this is about.
1906  *
1907  * \param initiator The channel that queued the async announcement
1908  */
1909 static void wait_for_initiator(struct ast_channel *initiator)
1910 {
1911         struct ast_datastore *async_datastore;
1912         struct async_datastore_data *add;
1913
1914         ast_channel_lock(initiator);
1915         async_datastore = ast_channel_datastore_find(initiator, &async_datastore_info, NULL);
1916         ast_channel_unlock(initiator);
1917
1918         if (!async_datastore) {
1919                 return;
1920         }
1921
1922         add = async_datastore->data;
1923
1924         ast_mutex_lock(&add->lock);
1925         while (add->wait) {
1926                 ast_cond_wait(&add->cond, &add->lock);
1927         }
1928         ast_mutex_unlock(&add->lock);
1929 }
1930
1931 /*!
1932  * \brief Play an announcement into a confbridge asynchronously
1933  *
1934  * This runs in the playback queue taskprocessor. This ensures that
1935  * all playbacks are handled in sequence and do not play over top one
1936  * another.
1937  *
1938  * \param data An async_playback_task_data
1939  * \return 0
1940  */
1941 static int async_playback_task(void *data)
1942 {
1943         struct async_playback_task_data *aptd = data;
1944
1945         /* Wait for the initiator to get back in the bridge or be hung up */
1946         if (aptd->initiator) {
1947                 wait_for_initiator(aptd->initiator);
1948         }
1949
1950         playback_common(aptd->conference, aptd->filename, aptd->say_number);
1951
1952         async_playback_task_data_destroy(aptd);
1953         return 0;
1954 }
1955
1956 static int async_play_sound_helper(struct confbridge_conference *conference,
1957         const char *filename, int say_number, struct ast_channel *initiator)
1958 {
1959         struct async_playback_task_data *aptd;
1960
1961         /* Do not waste resources trying to play files that do not exist */
1962         if (ast_strlen_zero(filename)) {
1963                 if (say_number < 0) {
1964                         return 0;
1965                 }
1966         } else if (!sound_file_exists(filename)) {
1967                 return 0;
1968         }
1969
1970         aptd = async_playback_task_data_alloc(conference, filename, say_number, initiator);
1971         if (!aptd) {
1972                 return -1;
1973         }
1974
1975         if (ast_taskprocessor_push(conference->playback_queue, async_playback_task, aptd)) {
1976                 if (!ast_strlen_zero(filename)) {
1977                         ast_log(LOG_WARNING, "Unable to play file '%s' to conference '%s'\n",
1978                                 filename, conference->name);
1979                 } else {
1980                         ast_log(LOG_WARNING, "Unable to say number '%d' to conference '%s'\n",
1981                                 say_number, conference->name);
1982                 }
1983                 async_playback_task_data_destroy(aptd);
1984                 return -1;
1985         }
1986
1987         return 0;
1988 }
1989
1990 int async_play_sound_file(struct confbridge_conference *conference,
1991         const char *filename, struct ast_channel *initiator)
1992 {
1993         return async_play_sound_helper(conference, filename, -1, initiator);
1994 }
1995
1996 void async_play_sound_ready(struct ast_channel *chan)
1997 {
1998         struct ast_datastore *async_datastore;
1999         struct async_datastore_data *add;
2000
2001         ast_channel_lock(chan);
2002         async_datastore = ast_channel_datastore_find(chan, &async_datastore_info, NULL);
2003         ast_channel_unlock(chan);
2004         if (!async_datastore) {
2005                 return;
2006         }
2007
2008         add = async_datastore->data;
2009
2010         ast_mutex_lock(&add->lock);
2011         add->wait = 0;
2012         ast_cond_signal(&add->cond);
2013         ast_mutex_unlock(&add->lock);
2014 }
2015
2016 /*!
2017  * \brief Play number into the conference bridge
2018  *
2019  * \param conference The conference bridge to say the number into
2020  * \param say_number number to say
2021  *
2022  * \retval 0 success
2023  * \retval -1 failure
2024  */
2025 static int play_sound_number(struct confbridge_conference *conference, int say_number)
2026 {
2027         return play_sound_helper(conference, NULL, say_number);
2028 }
2029
2030 static int conf_handle_talker_cb(struct ast_bridge_channel *bridge_channel, void *hook_pvt, int talking)
2031 {
2032         const struct confbridge_user *user = hook_pvt;
2033         RAII_VAR(struct confbridge_conference *, conference, NULL, ao2_cleanup);
2034         struct ast_json *talking_extras;
2035
2036         conference = ao2_find(conference_bridges, user->conference->name, OBJ_KEY);
2037         if (!conference) {
2038                 /* Remove the hook since the conference does not exist. */
2039                 return -1;
2040         }
2041
2042         talking_extras = ast_json_pack("{s: s, s: b}",
2043                 "talking_status", talking ? "on" : "off",
2044                 "admin", ast_test_flag(&user->u_profile, USER_OPT_ADMIN));
2045         if (!talking_extras) {
2046                 return 0;
2047         }
2048
2049         send_conf_stasis(conference, bridge_channel->chan, confbridge_talking_type(), talking_extras, 0);
2050         ast_json_unref(talking_extras);
2051         return 0;
2052 }
2053
2054 static int conf_get_pin(struct ast_channel *chan, struct confbridge_user *user)
2055 {
2056         char pin_guess[MAX_PIN+1] = { 0, };
2057         const char *pin = user->u_profile.pin;
2058         char *tmp = pin_guess;
2059         int i, res;
2060         unsigned int len = MAX_PIN;
2061
2062         /*
2063          * NOTE: We have not joined a conference yet so we have to use
2064          * the bridge profile requested by the user.
2065          */
2066
2067         /* give them three tries to get the pin right */
2068         for (i = 0; i < 3; i++) {
2069                 if (ast_app_getdata(chan,
2070                         conf_get_sound(CONF_SOUND_GET_PIN, user->b_profile.sounds),
2071                         tmp, len, 0) >= 0) {
2072                         if (!strcasecmp(pin, pin_guess)) {
2073                                 return 0;
2074                         }
2075                 }
2076                 ast_streamfile(chan,
2077                         conf_get_sound(CONF_SOUND_INVALID_PIN, user->b_profile.sounds),
2078                         ast_channel_language(chan));
2079                 res = ast_waitstream(chan, AST_DIGIT_ANY);
2080                 if (res > 0) {
2081                         /* Account for digit already read during ivalid pin playback
2082                          * resetting pin buf. */
2083                         pin_guess[0] = res;
2084                         pin_guess[1] = '\0';
2085                         tmp = pin_guess + 1;
2086                         len = MAX_PIN - 1;
2087                 } else {
2088                         /* reset pin buf as empty buffer. */
2089                         tmp = pin_guess;
2090                         len = MAX_PIN;
2091                 }
2092         }
2093         return -1;
2094 }
2095
2096 static int user_timeout(struct ast_bridge_channel *bridge_channel, void *ignore)
2097 {
2098         ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END, 0);
2099         pbx_builtin_setvar_helper(bridge_channel->chan, "CONFBRIDGE_RESULT", "TIMEOUT");
2100         return -1;
2101 }
2102
2103 static int conf_rec_name(struct confbridge_user *user, const char *conf_name)
2104 {
2105         char destdir[PATH_MAX];
2106         int res;
2107         int duration = 20;
2108
2109         snprintf(destdir, sizeof(destdir), "%s/confbridge", ast_config_AST_SPOOL_DIR);
2110
2111         if (ast_mkdir(destdir, 0777) != 0) {
2112                 ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", destdir, strerror(errno));
2113                 return -1;
2114         }
2115         snprintf(user->name_rec_location, sizeof(user->name_rec_location),
2116                  "%s/confbridge-name-%s-%s", destdir,
2117                  conf_name, ast_channel_uniqueid(user->chan));
2118
2119         if (!(ast_test_flag(&user->u_profile, USER_OPT_ANNOUNCE_JOIN_LEAVE_REVIEW))) {
2120                 res = ast_play_and_record(user->chan,
2121                         "vm-rec-name",
2122                         user->name_rec_location,
2123                         10,
2124                         "sln",
2125                         &duration,
2126                         NULL,
2127                         ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE),
2128                         0,
2129                         NULL);
2130         } else {
2131                 res = ast_record_review(user->chan,
2132                         "vm-rec-name",
2133                         user->name_rec_location,
2134                         10,
2135                         "sln",
2136                         &duration,
2137                         NULL);
2138         }
2139
2140         if (res == -1) {
2141                 user->name_rec_location[0] = '\0';
2142                 return -1;
2143         }
2144         return 0;
2145 }
2146
2147 static int join_callback(struct ast_bridge_channel *bridge_channel, void *ignore)
2148 {
2149         async_play_sound_ready(bridge_channel->chan);
2150         return 0;
2151 }
2152
2153 /*! \brief The ConfBridge application */
2154 static int confbridge_exec(struct ast_channel *chan, const char *data)
2155 {
2156         int res = 0, volume_adjustments[2];
2157         int quiet = 0;
2158         char *parse;
2159         const char *b_profile_name = NULL;
2160         const char *u_profile_name = NULL;
2161         const char *menu_profile_name = NULL;
2162         struct confbridge_conference *conference = NULL;
2163         struct confbridge_user user = {
2164                 .chan = chan,
2165                 .tech_args.talking_threshold = DEFAULT_TALKING_THRESHOLD,
2166                 .tech_args.silence_threshold = DEFAULT_SILENCE_THRESHOLD,
2167                 .tech_args.drop_silence = 0,
2168         };
2169         AST_DECLARE_APP_ARGS(args,
2170                 AST_APP_ARG(conf_name);
2171                 AST_APP_ARG(b_profile_name);
2172                 AST_APP_ARG(u_profile_name);
2173                 AST_APP_ARG(menu_profile_name);
2174         );
2175
2176         if (ast_channel_state(chan) != AST_STATE_UP) {
2177                 ast_answer(chan);
2178         }
2179
2180         if (ast_bridge_features_init(&user.features)) {
2181                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2182                 res = -1;
2183                 goto confbridge_cleanup;
2184         }
2185
2186         /* We need to make a copy of the input string if we are going to modify it! */
2187         parse = ast_strdupa(data);
2188
2189         AST_STANDARD_APP_ARGS(args, parse);
2190
2191         if (ast_strlen_zero(args.conf_name)) {
2192                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2193                 ast_log(LOG_WARNING, "%s requires an argument (conference name[,options])\n", app);
2194                 res = -1;
2195                 goto confbridge_cleanup;
2196         }
2197
2198         if (strlen(args.conf_name) >= MAX_CONF_NAME) {
2199                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2200                 ast_log(LOG_WARNING, "%s does not accept conference names longer than %d\n", app, MAX_CONF_NAME - 1);
2201                 res = -1;
2202                 goto confbridge_cleanup;
2203         }
2204
2205         /* bridge profile name */
2206         if (args.argc > 1 && !ast_strlen_zero(args.b_profile_name)) {
2207                 b_profile_name = args.b_profile_name;
2208         }
2209         if (!conf_find_bridge_profile(chan, b_profile_name, &user.b_profile)) {
2210                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2211                 ast_log(LOG_WARNING, "Conference bridge profile %s does not exist\n", b_profile_name ?
2212                         b_profile_name : DEFAULT_BRIDGE_PROFILE);
2213                 res = -1;
2214                 goto confbridge_cleanup;
2215         }
2216
2217         /* user profile name */
2218         if (args.argc > 2 && !ast_strlen_zero(args.u_profile_name)) {
2219                 u_profile_name = args.u_profile_name;
2220         }
2221         if (!conf_find_user_profile(chan, u_profile_name, &user.u_profile)) {
2222                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2223                 ast_log(LOG_WARNING, "Conference user profile %s does not exist\n", u_profile_name ?
2224                         u_profile_name : DEFAULT_USER_PROFILE);
2225                 res = -1;
2226                 goto confbridge_cleanup;
2227         }
2228
2229         quiet = ast_test_flag(&user.u_profile, USER_OPT_QUIET);
2230
2231         /* ask for a PIN immediately after finding user profile.  This has to be
2232          * prompted for requardless of quiet setting. */
2233         if (!ast_strlen_zero(user.u_profile.pin)) {
2234                 if (conf_get_pin(chan, &user)) {
2235                         pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2236                         res = -1; /* invalid PIN */
2237                         goto confbridge_cleanup;
2238                 }
2239         }
2240
2241         /* See if we need them to record a intro name */
2242         if (!quiet &&
2243                 (ast_test_flag(&user.u_profile, USER_OPT_ANNOUNCE_JOIN_LEAVE) ||
2244                 (ast_test_flag(&user.u_profile, USER_OPT_ANNOUNCE_JOIN_LEAVE_REVIEW)))) {
2245                 conf_rec_name(&user, args.conf_name);
2246         }
2247
2248         /* menu name */
2249         if (args.argc > 3 && !ast_strlen_zero(args.menu_profile_name)) {
2250                 menu_profile_name = args.menu_profile_name;
2251         }
2252
2253         if (conf_set_menu_to_user(chan, &user, menu_profile_name)) {
2254                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2255                 ast_log(LOG_WARNING, "Conference menu profile %s does not exist\n", menu_profile_name ?
2256                         menu_profile_name : DEFAULT_MENU_PROFILE);
2257                 res = -1;
2258                 goto confbridge_cleanup;
2259         }
2260
2261         /* Set if DTMF should pass through for this user or not */
2262         if (ast_test_flag(&user.u_profile, USER_OPT_DTMF_PASS)) {
2263                 user.features.dtmf_passthrough = 1;
2264         } else {
2265                 user.features.dtmf_passthrough = 0;
2266         }
2267
2268         /* Set dsp threshold values if present */
2269         if (user.u_profile.talking_threshold) {
2270                 user.tech_args.talking_threshold = user.u_profile.talking_threshold;
2271         }
2272         if (user.u_profile.silence_threshold) {
2273                 user.tech_args.silence_threshold = user.u_profile.silence_threshold;
2274         }
2275
2276         /* Set a talker indicate call back if talking detection is requested */
2277         if (ast_test_flag(&user.u_profile, USER_OPT_TALKER_DETECT)) {
2278                 if (ast_bridge_talk_detector_hook(&user.features, conf_handle_talker_cb,
2279                         &user, NULL, AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
2280                         pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2281                         res = -1;
2282                         goto confbridge_cleanup;
2283                 }
2284         }
2285
2286         /* Look for a conference bridge matching the provided name */
2287         if (!(conference = join_conference_bridge(args.conf_name, &user))) {
2288                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
2289                 res = -1;
2290                 goto confbridge_cleanup;
2291         }
2292
2293         /* Keep a copy of volume adjustments so we can restore them later if need be */
2294         volume_adjustments[0] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_READ);
2295         volume_adjustments[1] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_WRITE);
2296
2297         if (ast_test_flag(&user.u_profile, USER_OPT_DROP_SILENCE)) {
2298                 user.tech_args.drop_silence = 1;
2299         }
2300
2301         if (ast_test_flag(&user.u_profile, USER_OPT_JITTERBUFFER)) {
2302                 char *func_jb;
2303                 if ((func_jb = ast_module_helper("", "func_jitterbuffer", 0, 0, 0, 0))) {
2304                         ast_free(func_jb);
2305                         ast_func_write(chan, "JITTERBUFFER(adaptive)", "default");
2306                 }
2307         }
2308
2309         if (ast_test_flag(&user.u_profile, USER_OPT_DENOISE)) {
2310                 char *mod_speex;
2311                 /* Reduce background noise from each participant */
2312                 if ((mod_speex = ast_module_helper("", "codec_speex", 0, 0, 0, 0))) {
2313                         ast_free(mod_speex);
2314                         ast_func_write(chan, "DENOISE(rx)", "on");
2315                 }
2316         }
2317
2318         /* if this user has a intro, play it before entering */
2319         if (!ast_strlen_zero(user.name_rec_location)) {
2320                 ast_autoservice_start(chan);
2321                 play_sound_file(conference, user.name_rec_location);
2322                 play_sound_file(conference,
2323                         conf_get_sound(CONF_SOUND_HAS_JOINED, conference->b_profile.sounds));
2324                 ast_autoservice_stop(chan);
2325         }
2326
2327         /* Play the Join sound to both the conference and the user entering. */
2328         if (!quiet) {
2329                 const char *join_sound = conf_get_sound(CONF_SOUND_JOIN, conference->b_profile.sounds);
2330
2331                 if (strcmp(conference->b_profile.language, ast_channel_language(chan))) {
2332                         ast_stream_and_wait(chan, join_sound, "");
2333                         ast_autoservice_start(chan);
2334                         play_sound_file(conference, join_sound);
2335                         ast_autoservice_stop(chan);
2336                 } else {
2337                         async_play_sound_file(conference, join_sound, chan);
2338                 }
2339         }
2340
2341         if (user.u_profile.timeout) {
2342                 ast_bridge_interval_hook(&user.features,
2343                         0,
2344                         user.u_profile.timeout * 1000,
2345                         user_timeout,
2346                         NULL,
2347                         NULL,
2348                         AST_BRIDGE_HOOK_REMOVE_ON_PULL);
2349         }
2350
2351         /* See if we need to automatically set this user as a video source or not */
2352         handle_video_on_join(conference, user.chan, ast_test_flag(&user.u_profile, USER_OPT_MARKEDUSER));
2353
2354         conf_moh_unsuspend(&user);
2355
2356         /* Join our conference bridge for real */
2357         send_join_event(&user, conference);
2358
2359         if (ast_bridge_join_hook(&user.features, join_callback, NULL, NULL, 0)) {
2360                 async_play_sound_ready(user.chan);
2361         }
2362
2363         ast_bridge_join(conference->bridge,
2364                 chan,
2365                 NULL,
2366                 &user.features,
2367                 &user.tech_args,
2368                 0);
2369
2370         /* This is a catch-all in case joining the bridge failed or for some reason
2371          * an async announcement got queued up and hasn't been told to play yet
2372          */
2373         async_play_sound_ready(chan);
2374
2375         if (!user.kicked && ast_check_hangup(chan)) {
2376                 pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "HANGUP");
2377         }
2378
2379         send_leave_event(&user, conference);
2380
2381         /* if we're shutting down, don't attempt to do further processing */
2382         if (ast_shutting_down()) {
2383                 /*
2384                  * Not taking any new calls at this time.  We cannot create
2385                  * the announcer channel if this is the first channel into
2386                  * the conference and we certainly cannot create any
2387                  * recording channel.
2388                  */
2389                 leave_conference(&user);
2390                 conference = NULL;
2391                 goto confbridge_cleanup;
2392         }
2393
2394         /* If this user was a video source, we need to clean up and possibly pick a new source. */
2395         handle_video_on_exit(conference, user.chan);
2396
2397         /* if this user has a intro, play it when leaving */
2398         if (!quiet && !ast_strlen_zero(user.name_rec_location)) {
2399                 async_play_sound_file(conference, user.name_rec_location, NULL);
2400                 async_play_sound_file(conference,
2401                         conf_get_sound(CONF_SOUND_HAS_LEFT, conference->b_profile.sounds), NULL);
2402         }
2403
2404         /* play the leave sound */
2405         if (!quiet) {
2406                 const char *leave_sound = conf_get_sound(CONF_SOUND_LEAVE, conference->b_profile.sounds);
2407                 async_play_sound_file(conference, leave_sound, NULL);
2408         }
2409
2410         /* If the user was kicked from the conference play back the audio prompt for it */
2411         if (!quiet && user.kicked) {
2412                 res = ast_stream_and_wait(chan,
2413                         conf_get_sound(CONF_SOUND_KICKED, conference->b_profile.sounds),
2414                         "");
2415         }
2416
2417         /* Easy as pie, depart this channel from the conference bridge */
2418         leave_conference(&user);
2419         conference = NULL;
2420
2421         /* Restore volume adjustments to previous values in case they were changed */
2422         if (volume_adjustments[0]) {
2423                 ast_audiohook_volume_set(chan, AST_AUDIOHOOK_DIRECTION_READ, volume_adjustments[0]);
2424         }
2425         if (volume_adjustments[1]) {
2426                 ast_audiohook_volume_set(chan, AST_AUDIOHOOK_DIRECTION_WRITE, volume_adjustments[1]);
2427         }
2428
2429         if (!ast_strlen_zero(user.name_rec_location)) {
2430                 ast_filedelete(user.name_rec_location, NULL);
2431         }
2432
2433 confbridge_cleanup:
2434         ast_bridge_features_cleanup(&user.features);
2435         conf_bridge_profile_destroy(&user.b_profile);
2436         return res;
2437 }
2438
2439 static int action_toggle_mute(struct confbridge_conference *conference,
2440                               struct confbridge_user *user,
2441                               struct ast_bridge_channel *bridge_channel)
2442 {
2443         int mute;
2444
2445         /* Toggle user level mute request. */
2446         mute = !user->muted;
2447         generic_mute_unmute_user(conference, user, mute);
2448
2449         return play_file(bridge_channel, NULL,
2450                 conf_get_sound(mute ? CONF_SOUND_MUTED : CONF_SOUND_UNMUTED,
2451                         conference->b_profile.sounds)) < 0;
2452 }
2453
2454 static int action_toggle_mute_participants(struct confbridge_conference *conference, struct confbridge_user *user)
2455 {
2456         struct confbridge_user *cur_user = NULL;
2457         const char *sound_to_play;
2458         int mute;
2459
2460         ao2_lock(conference);
2461
2462         /* Toggle bridge level mute request. */
2463         mute = !conference->muted;
2464         conference->muted = mute;
2465
2466         AST_LIST_TRAVERSE(&conference->active_list, cur_user, list) {
2467                 if (!ast_test_flag(&cur_user->u_profile, USER_OPT_ADMIN)) {
2468                         /* Set user level to bridge level mute request. */
2469                         cur_user->muted = mute;
2470                         conf_update_user_mute(cur_user);
2471                 }
2472         }
2473
2474         ao2_unlock(conference);
2475
2476         sound_to_play = conf_get_sound(
2477                 mute ? CONF_SOUND_PARTICIPANTS_MUTED : CONF_SOUND_PARTICIPANTS_UNMUTED,
2478                 conference->b_profile.sounds);
2479
2480         if (strcmp(conference->b_profile.language, ast_channel_language(user->chan))) {
2481                 /* The host needs to hear it seperately, as they don't get the audio from play_sound_helper */
2482                 ast_stream_and_wait(user->chan, sound_to_play, "");
2483
2484                 /* Announce to the group that all participants are muted */
2485                 ast_autoservice_start(user->chan);
2486                 play_sound_file(conference, sound_to_play);
2487                 ast_autoservice_stop(user->chan);
2488         } else {
2489                 /* Playing the sound asynchronously lets the sound be heard by everyone at once */
2490                 async_play_sound_file(conference, sound_to_play, user->chan);
2491         }
2492
2493         return 0;
2494 }
2495
2496 static int action_playback(struct ast_bridge_channel *bridge_channel, const char *playback_file)
2497 {
2498         char *file_copy = ast_strdupa(playback_file);
2499         char *file = NULL;
2500
2501         while ((file = strsep(&file_copy, "&"))) {
2502                 if (ast_stream_and_wait(bridge_channel->chan, file, "")) {
2503                         ast_log(LOG_WARNING, "Failed to playback file %s to channel\n", file);
2504                         return -1;
2505                 }
2506         }
2507         return 0;
2508 }
2509
2510 static int action_playback_and_continue(struct confbridge_conference *conference,
2511         struct confbridge_user *user,
2512         struct ast_bridge_channel *bridge_channel,
2513         struct conf_menu *menu,
2514         const char *playback_file,
2515         const char *cur_dtmf,
2516         int *stop_prompts)
2517 {
2518         int i;
2519         int digit = 0;
2520         char dtmf[MAXIMUM_DTMF_FEATURE_STRING];
2521         struct conf_menu_entry new_menu_entry = { { 0, }, };
2522         char *file_copy = ast_strdupa(playback_file);
2523         char *file = NULL;
2524
2525         while ((file = strsep(&file_copy, "&"))) {
2526                 if (ast_streamfile(bridge_channel->chan, file, ast_channel_language(bridge_channel->chan))) {
2527                         ast_log(LOG_WARNING, "Failed to playback file %s to channel\n", file);
2528                         return -1;
2529                 }
2530
2531                 /* now wait for more digits. */
2532                 if (!(digit = ast_waitstream(bridge_channel->chan, AST_DIGIT_ANY))) {
2533                         /* streaming finished and no DTMF was entered */
2534                         continue;
2535                 } else if (digit == -1) {
2536                         /* error */
2537                         return -1;
2538                 } else {
2539                         break; /* dtmf was entered */
2540                 }
2541         }
2542         if (!digit) {
2543                 /* streaming finished on all files and no DTMF was entered */
2544                 return -1;
2545         }
2546         ast_stopstream(bridge_channel->chan);
2547
2548         /* If we get here, then DTMF has been entered, This means no
2549          * additional prompts should be played for this menu entry */
2550         *stop_prompts = 1;
2551
2552         /* If a digit was pressed during the payback, update
2553          * the dtmf string and look for a new menu entry in the
2554          * menu structure */
2555         ast_copy_string(dtmf, cur_dtmf, sizeof(dtmf));
2556         for (i = 0; i < (MAXIMUM_DTMF_FEATURE_STRING - 1); i++) {
2557                 dtmf[i] = cur_dtmf[i];
2558                 if (!dtmf[i]) {
2559                         dtmf[i] = (char) digit;
2560                         dtmf[i + 1] = '\0';
2561                         i = -1;
2562                         break;
2563                 }
2564         }
2565         /* If i is not -1 then the new dtmf digit was _NOT_ added to the string.
2566          * If this is the case, no new DTMF sequence should be looked for. */
2567         if (i != -1) {
2568                 return 0;
2569         }
2570
2571         if (conf_find_menu_entry_by_sequence(dtmf, menu, &new_menu_entry)) {
2572                 execute_menu_entry(conference,
2573                         user,
2574                         bridge_channel,
2575                         &new_menu_entry, menu);
2576                 conf_menu_entry_destroy(&new_menu_entry);
2577         }
2578         return 0;
2579 }
2580
2581 static int action_kick_last(struct confbridge_conference *conference,
2582         struct ast_bridge_channel *bridge_channel,
2583         struct confbridge_user *user)
2584 {
2585         struct confbridge_user *last_user = NULL;
2586         int isadmin = ast_test_flag(&user->u_profile, USER_OPT_ADMIN);
2587
2588         if (!isadmin) {
2589                 play_file(bridge_channel, NULL,
2590                         conf_get_sound(CONF_SOUND_ERROR_MENU, conference->b_profile.sounds));
2591                 ast_log(LOG_WARNING, "Only admin users can use the kick_last menu action. Channel %s of conf %s is not an admin.\n",
2592                         ast_channel_name(bridge_channel->chan),
2593                         conference->name);
2594                 return -1;
2595         }
2596
2597         ao2_lock(conference);
2598         if (((last_user = AST_LIST_LAST(&conference->active_list)) == user)
2599                 || (ast_test_flag(&last_user->u_profile, USER_OPT_ADMIN))) {
2600                 ao2_unlock(conference);
2601                 play_file(bridge_channel, NULL,
2602                         conf_get_sound(CONF_SOUND_ERROR_MENU, conference->b_profile.sounds));
2603         } else if (last_user && !last_user->kicked) {
2604                 last_user->kicked = 1;
2605                 pbx_builtin_setvar_helper(last_user->chan, "CONFBRIDGE_RESULT", "KICKED");
2606                 ast_bridge_remove(conference->bridge, last_user->chan);
2607                 ao2_unlock(conference);
2608         }
2609         return 0;
2610 }
2611
2612 static int action_dialplan_exec(struct ast_bridge_channel *bridge_channel, struct conf_menu_action *menu_action)
2613 {
2614         struct ast_pbx_args args;
2615         struct ast_pbx *pbx;
2616         char *exten;
2617         char *context;
2618         int priority;
2619         int res;
2620
2621         memset(&args, 0, sizeof(args));
2622         args.no_hangup_chan = 1;
2623
2624         ast_channel_lock(bridge_channel->chan);
2625
2626         /*save off*/
2627         exten = ast_strdupa(ast_channel_exten(bridge_channel->chan));
2628         context = ast_strdupa(ast_channel_context(bridge_channel->chan));
2629         priority = ast_channel_priority(bridge_channel->chan);
2630         pbx = ast_channel_pbx(bridge_channel->chan);
2631         ast_channel_pbx_set(bridge_channel->chan, NULL);
2632
2633         /*set new*/
2634         ast_channel_exten_set(bridge_channel->chan, menu_action->data.dialplan_args.exten);
2635         ast_channel_context_set(bridge_channel->chan, menu_action->data.dialplan_args.context);
2636         ast_channel_priority_set(bridge_channel->chan, menu_action->data.dialplan_args.priority);
2637
2638         ast_channel_unlock(bridge_channel->chan);
2639
2640         /*execute*/
2641         res = ast_pbx_run_args(bridge_channel->chan, &args);
2642
2643         /*restore*/
2644         ast_channel_lock(bridge_channel->chan);
2645
2646         ast_channel_exten_set(bridge_channel->chan, exten);
2647         ast_channel_context_set(bridge_channel->chan, context);
2648         ast_channel_priority_set(bridge_channel->chan, priority);
2649         ast_channel_pbx_set(bridge_channel->chan, pbx);
2650
2651         ast_channel_unlock(bridge_channel->chan);
2652
2653         return res;
2654 }
2655
2656 static int execute_menu_entry(struct confbridge_conference *conference,
2657         struct confbridge_user *user,
2658         struct ast_bridge_channel *bridge_channel,
2659         struct conf_menu_entry *menu_entry,
2660         struct conf_menu *menu)
2661 {
2662         struct conf_menu_action *menu_action;
2663         int isadmin = ast_test_flag(&user->u_profile, USER_OPT_ADMIN);
2664         int stop_prompts = 0;
2665         int res = 0;
2666
2667         AST_LIST_TRAVERSE(&menu_entry->actions, menu_action, action) {
2668                 switch (menu_action->id) {
2669                 case MENU_ACTION_TOGGLE_MUTE:
2670                         res |= action_toggle_mute(conference, user, bridge_channel);
2671                         break;
2672                 case MENU_ACTION_ADMIN_TOGGLE_MUTE_PARTICIPANTS:
2673                         if (!isadmin) {
2674                                 break;
2675                         }
2676                         action_toggle_mute_participants(conference, user);
2677                         break;
2678                 case MENU_ACTION_PARTICIPANT_COUNT:
2679                         announce_user_count(conference, user, bridge_channel);
2680                         break;
2681                 case MENU_ACTION_PLAYBACK:
2682                         if (!stop_prompts) {
2683                                 res |= action_playback(bridge_channel, menu_action->data.playback_file);
2684                                 ast_test_suite_event_notify("CONF_MENU_PLAYBACK",
2685                                         "Message: %s\r\nChannel: %s",
2686                                         menu_action->data.playback_file, ast_channel_name(bridge_channel->chan));
2687                         }
2688                         break;
2689                 case MENU_ACTION_RESET_LISTENING:
2690                         ast_audiohook_volume_set(user->chan, AST_AUDIOHOOK_DIRECTION_WRITE, 0);
2691                         break;
2692                 case MENU_ACTION_RESET_TALKING:
2693                         ast_audiohook_volume_set(user->chan, AST_AUDIOHOOK_DIRECTION_READ, 0);
2694                         break;
2695                 case MENU_ACTION_INCREASE_LISTENING:
2696                         ast_audiohook_volume_adjust(user->chan,
2697                                 AST_AUDIOHOOK_DIRECTION_WRITE, 1);
2698                         break;
2699                 case MENU_ACTION_DECREASE_LISTENING:
2700                         ast_audiohook_volume_adjust(user->chan,
2701                                 AST_AUDIOHOOK_DIRECTION_WRITE, -1);
2702                         break;
2703                 case MENU_ACTION_INCREASE_TALKING:
2704                         ast_audiohook_volume_adjust(user->chan,
2705                                 AST_AUDIOHOOK_DIRECTION_READ, 1);
2706                         break;
2707                 case MENU_ACTION_DECREASE_TALKING:
2708                         ast_audiohook_volume_adjust(user->chan,
2709                                 AST_AUDIOHOOK_DIRECTION_READ, -1);
2710                         break;
2711                 case MENU_ACTION_PLAYBACK_AND_CONTINUE:
2712                         if (!(stop_prompts)) {
2713                                 res |= action_playback_and_continue(conference,
2714                                         user,
2715                                         bridge_channel,
2716                                         menu,
2717                                         menu_action->data.playback_file,
2718                                         menu_entry->dtmf,
2719                                         &stop_prompts);
2720                         }
2721                         break;
2722                 case MENU_ACTION_DIALPLAN_EXEC:
2723                         res |= action_dialplan_exec(bridge_channel, menu_action);
2724                         break;
2725                 case MENU_ACTION_ADMIN_TOGGLE_LOCK:
2726                         if (!isadmin) {
2727                                 break;
2728                         }
2729                         conference->locked = (!conference->locked ? 1 : 0);
2730                         res |= play_file(bridge_channel, NULL,
2731                                 conf_get_sound(
2732                                         conference->locked ? CONF_SOUND_LOCKED_NOW : CONF_SOUND_UNLOCKED_NOW,
2733                                         conference->b_profile.sounds)) < 0;
2734                         break;
2735                 case MENU_ACTION_ADMIN_KICK_LAST:
2736                         res |= action_kick_last(conference, bridge_channel, user);
2737                         break;
2738                 case MENU_ACTION_LEAVE:
2739                         pbx_builtin_setvar_helper(bridge_channel->chan, "CONFBRIDGE_RESULT", "DTMF");
2740                         ao2_lock(conference);
2741                         ast_bridge_remove(conference->bridge, bridge_channel->chan);
2742                         ast_test_suite_event_notify("CONF_MENU_LEAVE",
2743                                 "Channel: %s",
2744                                 ast_channel_name(bridge_channel->chan));
2745                         ao2_unlock(conference);
2746                         break;
2747                 case MENU_ACTION_NOOP:
2748                         break;
2749                 case MENU_ACTION_SET_SINGLE_VIDEO_SRC:
2750                         ao2_lock(conference);
2751                         ast_bridge_set_single_src_video_mode(conference->bridge, bridge_channel->chan);
2752                         ao2_unlock(conference);
2753                         break;
2754                 case MENU_ACTION_RELEASE_SINGLE_VIDEO_SRC:
2755                         handle_video_on_exit(conference, bridge_channel->chan);
2756                         break;
2757                 }
2758         }
2759         return res;
2760 }
2761
2762 int conf_handle_dtmf(struct ast_bridge_channel *bridge_channel,
2763         struct confbridge_user *user,
2764         struct conf_menu_entry *menu_entry,
2765         struct conf_menu *menu)
2766 {
2767         /* See if music on hold is playing */
2768         conf_moh_suspend(user);
2769
2770         /* execute the list of actions associated with this menu entry */
2771         execute_menu_entry(user->conference, user, bridge_channel, menu_entry, menu);
2772
2773         /* See if music on hold needs to be started back up again */
2774         conf_moh_unsuspend(user);
2775
2776         async_play_sound_ready(bridge_channel->chan);
2777
2778         return 0;
2779 }
2780
2781 static int kick_conference_participant(struct confbridge_conference *conference,
2782         const char *channel)
2783 {
2784         int res = -1;
2785         int match;
2786         struct confbridge_user *user = NULL;
2787         int all = !strcasecmp("all", channel);
2788         int participants = !strcasecmp("participants", channel);
2789
2790         SCOPED_AO2LOCK(bridge_lock, conference);
2791
2792         AST_LIST_TRAVERSE(&conference->active_list, user, list) {
2793                 if (user->kicked) {
2794                         continue;
2795                 }
2796                 match = !strcasecmp(channel, ast_channel_name(user->chan));
2797                 if (match || all
2798                                 || (participants && !ast_test_flag(&user->u_profile, USER_OPT_ADMIN))) {
2799                         user->kicked = 1;
2800                         pbx_builtin_setvar_helper(user->chan, "CONFBRIDGE_RESULT", "KICKED");
2801                         ast_bridge_remove(conference->bridge, user->chan);
2802                         res = 0;
2803                         if (match) {
2804                                 return res;
2805                         }
2806                 }
2807         }
2808         AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
2809                 if (user->kicked) {
2810                         continue;
2811                 }
2812                 match = !strcasecmp(channel, ast_channel_name(user->chan));
2813                 if (match || all
2814                                 || (participants && !ast_test_flag(&user->u_profile, USER_OPT_ADMIN))) {
2815                         user->kicked = 1;
2816                         pbx_builtin_setvar_helper(user->chan, "CONFBRIDGE_RESULT", "KICKED");
2817                         ast_bridge_remove(conference->bridge, user->chan);
2818                         res = 0;
2819                         if (match) {
2820                                 return res;
2821                         }
2822                 }
2823         }
2824
2825         return res;
2826 }
2827
2828 static char *complete_confbridge_name(const char *line, const char *word, int pos, int state)
2829 {
2830         int which = 0;
2831         struct confbridge_conference *conference;
2832         char *res = NULL;
2833         int wordlen = strlen(word);
2834         struct ao2_iterator iter;
2835
2836         iter = ao2_iterator_init(conference_bridges, 0);
2837         while ((conference = ao2_iterator_next(&iter))) {
2838                 if (!strncasecmp(conference->name, word, wordlen) && ++which > state) {
2839                         res = ast_strdup(conference->name);
2840                         ao2_ref(conference, -1);
2841                         break;
2842                 }
2843                 ao2_ref(conference, -1);
2844         }
2845         ao2_iterator_destroy(&iter);
2846
2847         return res;
2848 }
2849
2850 static char *complete_confbridge_participant(const char *conference_name, const char *line, const char *word, int pos, int state)
2851 {
2852         int which = 0;
2853         RAII_VAR(struct confbridge_conference *, conference, NULL, ao2_cleanup);
2854         struct confbridge_user *user;
2855         char *res = NULL;
2856         int wordlen = strlen(word);
2857
2858         conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
2859         if (!conference) {
2860                 return NULL;
2861         }
2862
2863         if (!strncasecmp("all", word, wordlen) && ++which > state) {
2864                 return ast_strdup("all");
2865         }
2866
2867         if (!strncasecmp("participants", word, wordlen) && ++which > state) {
2868                 return ast_strdup("participants");
2869         }
2870
2871         {
2872                 SCOPED_AO2LOCK(bridge_lock, conference);
2873                 AST_LIST_TRAVERSE(&conference->active_list, user, list) {
2874                         if (!strncasecmp(ast_channel_name(user->chan), word, wordlen) && ++which > state) {
2875                                 res = ast_strdup(ast_channel_name(user->chan));
2876                                 return res;
2877                         }
2878                 }
2879                 AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
2880                         if (!strncasecmp(ast_channel_name(user->chan), word, wordlen) && ++which > state) {
2881                                 res = ast_strdup(ast_channel_name(user->chan));
2882                                 return res;
2883                         }
2884                 }
2885         }
2886
2887         return NULL;
2888 }
2889
2890 static char *handle_cli_confbridge_kick(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2891 {
2892         struct confbridge_conference *conference;
2893         int not_found;
2894
2895         switch (cmd) {
2896         case CLI_INIT:
2897                 e->command = "confbridge kick";
2898                 e->usage =
2899                         "Usage: confbridge kick <conference> <channel>\n"
2900                         "       Kicks a channel out of the conference bridge.\n"
2901                         "             (all to kick everyone, participants to kick non-admins).\n";
2902                 return NULL;
2903         case CLI_GENERATE:
2904                 if (a->pos == 2) {
2905                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
2906                 }
2907                 if (a->pos == 3) {
2908                         return complete_confbridge_participant(a->argv[2], a->line, a->word, a->pos, a->n);
2909                 }
2910                 return NULL;
2911         }
2912
2913         if (a->argc != 4) {
2914                 return CLI_SHOWUSAGE;
2915         }
2916
2917         conference = ao2_find(conference_bridges, a->argv[2], OBJ_KEY);
2918         if (!conference) {
2919                 ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
2920                 return CLI_SUCCESS;
2921         }
2922         not_found = kick_conference_participant(conference, a->argv[3]);
2923         ao2_ref(conference, -1);
2924         if (not_found) {
2925                 if (!strcasecmp("all", a->argv[3]) || !strcasecmp("participants", a->argv[3])) {
2926                         ast_cli(a->fd, "No participants found!\n");
2927                 } else {
2928                         ast_cli(a->fd, "No participant named '%s' found!\n", a->argv[3]);
2929                 }
2930                 return CLI_SUCCESS;
2931         }
2932         ast_cli(a->fd, "Kicked '%s' out of conference '%s'\n", a->argv[3], a->argv[2]);
2933         return CLI_SUCCESS;
2934 }
2935
2936 static void handle_cli_confbridge_list_item(struct ast_cli_args *a, struct confbridge_user *user, int waiting)
2937 {
2938         char flag_str[6 + 1];/* Max flags + terminator */
2939         int pos = 0;
2940
2941         /* Build flags column string. */
2942         if (ast_test_flag(&user->u_profile, USER_OPT_ADMIN)) {
2943                 flag_str[pos++] = 'A';
2944         }
2945         if (ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER)) {
2946                 flag_str[pos++] = 'M';
2947         }
2948         if (ast_test_flag(&user->u_profile, USER_OPT_WAITMARKED)) {
2949                 flag_str[pos++] = 'W';
2950         }
2951         if (ast_test_flag(&user->u_profile, USER_OPT_ENDMARKED)) {
2952                 flag_str[pos++] = 'E';
2953         }
2954         if (user->muted) {
2955                 flag_str[pos++] = 'm';
2956         }
2957         if (waiting) {
2958                 flag_str[pos++] = 'w';
2959         }
2960         flag_str[pos] = '\0';
2961
2962         ast_cli(a->fd, "%-30s %-6s %-16s %-16s %-16s %s\n",
2963                 ast_channel_name(user->chan),
2964                 flag_str,
2965                 user->u_profile.name,
2966                 user->conference->b_profile.name,
2967                 user->menu_name,
2968                 S_COR(ast_channel_caller(user->chan)->id.number.valid,
2969                         ast_channel_caller(user->chan)->id.number.str, "<unknown>"));
2970 }
2971
2972 static char *handle_cli_confbridge_list(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2973 {
2974         struct confbridge_conference *conference;
2975
2976         switch (cmd) {
2977         case CLI_INIT:
2978                 e->command = "confbridge list";
2979                 e->usage =
2980                         "Usage: confbridge list [<name>]\n"
2981                         "       Lists all currently active conference bridges or a specific conference bridge.\n"
2982                         "\n"
2983                         "       When a conference bridge name is provided, flags may be shown for users. Below\n"
2984                         "       are the flags and what they represent.\n"
2985                         "\n"
2986                         "       Flags:\n"
2987                         "         A - The user is an admin\n"
2988                         "         M - The user is a marked user\n"
2989                         "         W - The user must wait for a marked user to join\n"
2990                         "         E - The user will be kicked after the last marked user leaves the conference\n"
2991                         "         m - The user is muted\n"
2992                         "         w - The user is waiting for a marked user to join\n";
2993                 return NULL;
2994         case CLI_GENERATE:
2995                 if (a->pos == 2) {
2996                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
2997                 }
2998                 return NULL;
2999         }
3000
3001         if (a->argc == 2) {
3002                 struct ao2_iterator iter;
3003
3004                 ast_cli(a->fd, "Conference Bridge Name           Users  Marked Locked Muted\n");
3005                 ast_cli(a->fd, "================================ ====== ====== ====== =====\n");
3006                 iter = ao2_iterator_init(conference_bridges, 0);
3007                 while ((conference = ao2_iterator_next(&iter))) {
3008                         ast_cli(a->fd, "%-32s %6u %6u %-6s %s\n",
3009                                 conference->name,
3010                                 conference->activeusers + conference->waitingusers,
3011                                 conference->markedusers,
3012                                 AST_CLI_YESNO(conference->locked),
3013                                 AST_CLI_YESNO(conference->muted));
3014                         ao2_ref(conference, -1);
3015                 }
3016                 ao2_iterator_destroy(&iter);
3017                 return CLI_SUCCESS;
3018         }
3019
3020         if (a->argc == 3) {
3021                 struct confbridge_user *user;
3022
3023                 conference = ao2_find(conference_bridges, a->argv[2], OBJ_KEY);
3024                 if (!conference) {
3025                         ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
3026                         return CLI_SUCCESS;
3027                 }
3028                 ast_cli(a->fd, "Channel                        Flags  User Profile     Bridge Profile   Menu             CallerID\n");
3029                 ast_cli(a->fd, "============================== ====== ================ ================ ================ ================\n");
3030                 ao2_lock(conference);
3031                 AST_LIST_TRAVERSE(&conference->active_list, user, list) {
3032                         handle_cli_confbridge_list_item(a, user, 0);
3033                 }
3034                 AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
3035                         handle_cli_confbridge_list_item(a, user, 1);
3036                 }
3037                 ao2_unlock(conference);
3038                 ao2_ref(conference, -1);
3039                 return CLI_SUCCESS;
3040         }
3041
3042         return CLI_SHOWUSAGE;
3043 }
3044
3045 /* \internal
3046  * \brief finds a conference by name and locks/unlocks.
3047  *
3048  * \retval 0 success
3049  * \retval -1 conference not found
3050  */
3051 static int generic_lock_unlock_helper(int lock, const char *conference_name)
3052 {
3053         struct confbridge_conference *conference;
3054         int res = 0;
3055
3056         conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
3057         if (!conference) {
3058                 return -1;
3059         }
3060         ao2_lock(conference);
3061         conference->locked = lock;
3062         ast_test_suite_event_notify("CONF_LOCK", "Message: conference %s\r\nConference: %s", conference->locked ? "locked" : "unlocked", conference->b_profile.name);
3063         ao2_unlock(conference);
3064         ao2_ref(conference, -1);
3065
3066         return res;
3067 }
3068
3069 /* \internal
3070  * \brief finds a conference user by channel name and mutes/unmutes them.
3071  *
3072  * \retval 0 success
3073  * \retval -1 conference not found
3074  * \retval -2 user not found
3075  */
3076 static int generic_mute_unmute_helper(int mute, const char *conference_name,
3077         const char *chan_name)
3078 {
3079         RAII_VAR(struct confbridge_conference *, conference, NULL, ao2_cleanup);
3080         struct confbridge_user *user;
3081         int all = !strcasecmp("all", chan_name);
3082         int participants = !strcasecmp("participants", chan_name);
3083         int res = -2;
3084
3085         conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
3086         if (!conference) {
3087                 return -1;
3088         }
3089
3090         {
3091                 SCOPED_AO2LOCK(bridge_lock, conference);
3092                 AST_LIST_TRAVERSE(&conference->active_list, user, list) {
3093                         int match = !strncasecmp(chan_name, ast_channel_name(user->chan),
3094                                 strlen(chan_name));
3095                         if (match || all
3096                                 || (participants && !ast_test_flag(&user->u_profile, USER_OPT_ADMIN))) {
3097                                 generic_mute_unmute_user(conference, user, mute);
3098                                 res = 0;
3099                                 if (match) {
3100                                         return res;
3101                                 }
3102                         }
3103                 }
3104
3105                 AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
3106                         int match = !strncasecmp(chan_name, ast_channel_name(user->chan),
3107                                 strlen(chan_name));
3108                         if (match || all
3109                                 || (participants && !ast_test_flag(&user->u_profile, USER_OPT_ADMIN))) {
3110                                 generic_mute_unmute_user(conference, user, mute);
3111                                 res = 0;
3112                                 if (match) {
3113                                         return res;
3114                                 }
3115                         }
3116                 }
3117         }
3118
3119         return res;
3120 }
3121
3122 static int cli_mute_unmute_helper(int mute, struct ast_cli_args *a)
3123 {
3124         int res = generic_mute_unmute_helper(mute, a->argv[2], a->argv[3]);
3125
3126         if (res == -1) {
3127                 ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
3128                 return -1;
3129         } else if (res == -2) {
3130                 if (!strcasecmp("all", a->argv[3]) || !strcasecmp("participants", a->argv[3])) {
3131                         ast_cli(a->fd, "No participants found in conference %s\n", a->argv[2]);
3132                 } else {
3133                         ast_cli(a->fd, "No channel named '%s' found in conference %s\n", a->argv[3], a->argv[2]);
3134                 }
3135                 return -1;
3136         }
3137         ast_cli(a->fd, "%s %s from confbridge %s\n", mute ? "Muting" : "Unmuting", a->argv[3], a->argv[2]);
3138         return 0;
3139 }
3140
3141 static char *handle_cli_confbridge_mute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3142 {
3143         switch (cmd) {
3144         case CLI_INIT:
3145                 e->command = "confbridge mute";
3146                 e->usage =
3147                         "Usage: confbridge mute <conference> <channel>\n"
3148                         "       Mute a channel in a conference.\n"
3149                         "              (all to mute everyone, participants to mute non-admins)\n"
3150                         "       If the specified channel is a prefix,\n"
3151                         "       the action will be taken on the first\n"
3152                         "       matching channel.\n";
3153                 return NULL;
3154         case CLI_GENERATE:
3155                 if (a->pos == 2) {
3156                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
3157                 }
3158                 if (a->pos == 3) {
3159                         return complete_confbridge_participant(a->argv[2], a->line, a->word, a->pos, a->n);
3160                 }
3161                 return NULL;
3162         }
3163         if (a->argc != 4) {
3164                 return CLI_SHOWUSAGE;
3165         }
3166
3167         cli_mute_unmute_helper(1, a);
3168
3169         return CLI_SUCCESS;
3170 }
3171
3172 static char *handle_cli_confbridge_unmute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3173 {
3174         switch (cmd) {
3175         case CLI_INIT:
3176                 e->command = "confbridge unmute";
3177                 e->usage =
3178                         "Usage: confbridge unmute <conference> <channel>\n"
3179                         "       Unmute a channel in a conference.\n"
3180                         "              (all to unmute everyone, participants to unmute non-admins)\n"
3181                         "       If the specified channel is a prefix,\n"
3182                         "       the action will be taken on the first\n"
3183                         "       matching channel.\n";
3184                 return NULL;
3185         case CLI_GENERATE:
3186                 if (a->pos == 2) {
3187                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
3188                 }
3189                 if (a->pos == 3) {
3190                         return complete_confbridge_participant(a->argv[2], a->line, a->word, a->pos, a->n);
3191                 }
3192                 return NULL;
3193         }
3194         if (a->argc != 4) {
3195                 return CLI_SHOWUSAGE;
3196         }
3197
3198         cli_mute_unmute_helper(0, a);
3199
3200         return CLI_SUCCESS;
3201 }
3202
3203 static char *handle_cli_confbridge_lock(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3204 {
3205         switch (cmd) {
3206         case CLI_INIT:
3207                 e->command = "confbridge lock";
3208                 e->usage =
3209                         "Usage: confbridge lock <conference>\n"
3210                         "       Lock a conference. While locked, no new non-admins\n"
3211                         "       may join the conference.\n";
3212                 return NULL;
3213         case CLI_GENERATE:
3214                 if (a->pos == 2) {
3215                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
3216                 }
3217                 return NULL;
3218         }
3219         if (a->argc != 3) {
3220                 return CLI_SHOWUSAGE;
3221         }
3222         if (generic_lock_unlock_helper(1, a->argv[2])) {
3223                 ast_cli(a->fd, "Conference %s is not found\n", a->argv[2]);
3224         } else {
3225                 ast_cli(a->fd, "Conference %s is locked.\n", a->argv[2]);
3226         }
3227         return CLI_SUCCESS;
3228 }
3229
3230 static char *handle_cli_confbridge_unlock(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3231 {
3232         switch (cmd) {
3233         case CLI_INIT:
3234                 e->command = "confbridge unlock";
3235                 e->usage =
3236                         "Usage: confbridge unlock <conference>\n"
3237                         "       Unlock a previously locked conference.\n";
3238                 return NULL;
3239         case CLI_GENERATE:
3240                 if (a->pos == 2) {
3241                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
3242                 }
3243                 return NULL;
3244         }
3245         if (a->argc != 3) {
3246                 return CLI_SHOWUSAGE;
3247         }
3248         if (generic_lock_unlock_helper(0, a->argv[2])) {
3249                 ast_cli(a->fd, "Conference %s is not found\n", a->argv[2]);
3250         } else {
3251                 ast_cli(a->fd, "Conference %s is unlocked.\n", a->argv[2]);
3252         }
3253         return CLI_SUCCESS;
3254 }
3255
3256 static char *handle_cli_confbridge_start_record(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3257 {
3258         const char *rec_file = NULL;
3259         struct confbridge_conference *conference;
3260
3261         switch (cmd) {
3262         case CLI_INIT:
3263                 e->command = "confbridge record start";
3264                 e->usage =
3265                         "Usage: confbridge record start <conference> <file>\n"
3266                         "       <file> is optional, Otherwise the bridge profile\n"
3267                         "       record file will be used.  If the bridge profile\n"
3268                         "       has no record file specified, a file will automatically\n"
3269                         "       be generated in the monitor directory\n";
3270                 return NULL;
3271         case CLI_GENERATE:
3272                 if (a->pos == 3) {
3273                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
3274                 }
3275                 return NULL;
3276         }
3277         if (a->argc < 4) {
3278                 return CLI_SHOWUSAGE;
3279         }
3280         if (a->argc == 5) {
3281                 rec_file = a->argv[4];
3282         }
3283
3284         conference = ao2_find(conference_bridges, a->argv[3], OBJ_KEY);
3285         if (!conference) {
3286                 ast_cli(a->fd, "Conference not found.\n");
3287                 return CLI_FAILURE;
3288         }
3289         ao2_lock(conference);
3290         if (conf_is_recording(conference)) {
3291                 ast_cli(a->fd, "Conference is already being recorded.\n");
3292                 ao2_unlock(conference);
3293                 ao2_ref(conference, -1);
3294                 return CLI_SUCCESS;
3295         }
3296         if (!ast_strlen_zero(rec_file)) {
3297                 ast_copy_string(conference->b_profile.rec_file, rec_file, sizeof(conference->b_profile.rec_file));
3298         }
3299
3300         if (conf_start_record(conference)) {
3301                 ast_cli(a->fd, "Could not start recording due to internal error.\n");
3302                 ao2_unlock(conference);
3303                 ao2_ref(conference, -1);
3304                 return CLI_FAILURE;
3305         }
3306         ao2_unlock(conference);
3307
3308         ast_cli(a->fd, "Recording started\n");
3309         ao2_ref(conference, -1);
3310         return CLI_SUCCESS;
3311 }
3312
3313 static char *handle_cli_confbridge_stop_record(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3314 {
3315         struct confbridge_conference *conference;
3316         int ret;
3317
3318         switch (cmd) {
3319         case CLI_INIT:
3320                 e->command = "confbridge record stop";
3321                 e->usage =
3322                         "Usage: confbridge record stop <conference>\n"
3323                         "       Stop a previously started recording.\n";
3324                 return NULL;
3325         case CLI_GENERATE:
3326                 if (a->pos == 3) {
3327                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
3328                 }
3329                 return NULL;
3330         }
3331         if (a->argc != 4) {
3332                 return CLI_SHOWUSAGE;
3333         }
3334
3335         conference = ao2_find(conference_bridges, a->argv[3], OBJ_KEY);
3336         if (!conference) {
3337                 ast_cli(a->fd, "Conference not found.\n");
3338                 return CLI_SUCCESS;
3339         }
3340         ao2_lock(conference);
3341         ret = conf_stop_record(conference);
3342         ao2_unlock(conference);
3343         ast_cli(a->fd, "Recording %sstopped.\n", ret ? "could not be " : "");
3344         ao2_ref(conference, -1);
3345         return CLI_SUCCESS;
3346 }
3347
3348 static struct ast_cli_entry cli_confbridge[] = {
3349         AST_CLI_DEFINE(handle_cli_confbridge_list, "List conference bridges and participants."),
3350         AST_CLI_DEFINE(handle_cli_confbridge_kick, "Kick participants out of conference bridges."),
3351         AST_CLI_DEFINE(handle_cli_confbridge_mute, "Mute participants."),
3352         AST_CLI_DEFINE(handle_cli_confbridge_unmute, "Unmute participants."),
3353         AST_CLI_DEFINE(handle_cli_confbridge_lock, "Lock a conference."),
3354         AST_CLI_DEFINE(handle_cli_confbridge_unlock, "Unlock a conference."),
3355         AST_CLI_DEFINE(handle_cli_confbridge_start_record, "Start recording a conference"),
3356         AST_CLI_DEFINE(handle_cli_confbridge_stop_record, "Stop recording a conference."),
3357 };
3358 static struct ast_custom_function confbridge_function = {
3359         .name = "CONFBRIDGE",
3360         .write = func_confbridge_helper,
3361 };
3362
3363 static int func_confbridge_info(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len);
3364 static struct ast_custom_function confbridge_info_function = {
3365         .name = "CONFBRIDGE_INFO",
3366         .read = func_confbridge_info,
3367 };
3368
3369 static void action_confbridgelist_item(struct mansession *s, const char *id_text, struct confbridge_conference *conference, struct confbridge_user *user, int waiting)
3370 {
3371         astman_append(s,
3372                 "Event: ConfbridgeList\r\n"
3373                 "%s"
3374                 "Conference: %s\r\n"
3375                 "CallerIDNum: %s\r\n"
3376                 "CallerIDName: %s\r\n"
3377                 "Channel: %s\r\n"
3378                 "Admin: %s\r\n"
3379                 "MarkedUser: %s\r\n"
3380                 "WaitMarked: %s\r\n"
3381                 "EndMarked: %s\r\n"
3382                 "Waiting: %s\r\n"
3383                 "Muted: %s\r\n"
3384                 "AnsweredTime: %d\r\n"
3385                 "\r\n",
3386                 id_text,
3387                 conference->name,
3388                 S_COR(ast_channel_caller(user->chan)->id.number.valid, ast_channel_caller(user->chan)->id.number.str, "<unknown>"),
3389                 S_COR(ast_channel_caller(user->chan)->id.name.valid, ast_channel_caller(user->chan)->id.name.str, "<no name>"),
3390                 ast_channel_name(user->chan),
3391                 ast_test_flag(&user->u_profile, USER_OPT_ADMIN) ? "Yes" : "No",
3392                 ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER) ? "Yes" : "No",
3393                 ast_test_flag(&user->u_profile, USER_OPT_WAITMARKED) ? "Yes" : "No",
3394                 ast_test_flag(&user->u_profile, USER_OPT_ENDMARKED) ? "Yes" : "No",
3395                 waiting ? "Yes" : "No",
3396                 user->muted ? "Yes" : "No",
3397                 ast_channel_get_up_time(user->chan));
3398 }
3399
3400 static int action_confbridgelist(struct mansession *s, const struct message *m)
3401 {
3402         const char *actionid = astman_get_header(m, "ActionID");
3403         const char *conference_name = astman_get_header(m, "Conference");
3404         struct confbridge_user *user;
3405         struct confbridge_conference *conference;
3406         char id_text[80];
3407         int total = 0;
3408
3409         id_text[0] = '\0';
3410         if (!ast_strlen_zero(actionid)) {
3411                 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", actionid);
3412         }
3413         if (ast_strlen_zero(conference_name)) {
3414                 astman_send_error(s, m, "No Conference name provided.");
3415                 return 0;
3416         }
3417         if (!ao2_container_count(conference_bridges)) {
3418                 astman_send_error(s, m, "No active conferences.");
3419                 return 0;
3420         }
3421         conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
3422         if (!conference) {
3423                 astman_send_error(s, m, "No Conference by that name found.");
3424                 return 0;
3425         }
3426
3427         astman_send_listack(s, m, "Confbridge user list will follow", "start");
3428
3429         ao2_lock(conference);
3430         AST_LIST_TRAVERSE(&conference->active_list, user, list) {
3431                 total++;
3432                 action_confbridgelist_item(s, id_text, conference, user, 0);
3433         }
3434         AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
3435                 total++;
3436                 action_confbridgelist_item(s, id_text, conference, user, 1);
3437         }
3438         ao2_unlock(conference);
3439         ao2_ref(conference, -1);
3440
3441         astman_send_list_complete_start(s, m, "ConfbridgeListComplete", total);
3442         astman_send_list_complete_end(s);
3443
3444         return 0;
3445 }
3446
3447 static int action_confbridgelistrooms(struct mansession *s, const struct message *m)
3448 {
3449         const char *actionid = astman_get_header(m, "ActionID");
3450         struct confbridge_conference *conference;
3451         struct ao2_iterator iter;
3452         char id_text[512] = "";
3453         int totalitems = 0;
3454
3455         if (!ast_strlen_zero(actionid)) {
3456                 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", actionid);
3457         }
3458
3459         if (!ao2_container_count(conference_bridges)) {
3460                 astman_send_error(s, m, "No active conferences.");
3461                 return 0;
3462         }
3463
3464         astman_send_listack(s, m, "Confbridge conferences will follow", "start");
3465
3466         /* Traverse the conference list */
3467         iter = ao2_iterator_init(conference_bridges, 0);
3468         while ((conference = ao2_iterator_next(&iter))) {
3469                 totalitems++;
3470
3471                 ao2_lock(conference);
3472                 astman_append(s,
3473                 "Event: ConfbridgeListRooms\r\n"
3474                 "%s"
3475                 "Conference: %s\r\n"
3476                 "Parties: %u\r\n"
3477                 "Marked: %u\r\n"
3478                 "Locked: %s\r\n"
3479                 "Muted: %s\r\n"
3480                 "\r\n",
3481                 id_text,
3482                 conference->name,
3483                 conference->activeusers + conference->waitingusers,
3484                 conference->markedusers,
3485                 AST_YESNO(conference->locked),
3486                 AST_YESNO(conference->muted));
3487                 ao2_unlock(conference);
3488
3489                 ao2_ref(conference, -1);
3490         }
3491         ao2_iterator_destroy(&iter);
3492
3493         /* Send final confirmation */
3494         astman_send_list_complete_start(s, m, "ConfbridgeListRoomsComplete", totalitems);
3495         astman_send_list_complete_end(s);
3496         return 0;
3497 }
3498
3499 static int action_mute_unmute_helper(struct mansession *s, const struct message *m, int mute)
3500 {
3501         const char *conference_name = astman_get_header(m, "Conference");
3502         const char *channel_name = astman_get_header(m, "Channel");
3503         int res = 0;
3504
3505         if (ast_strlen_zero(conference_name)) {
3506                 astman_send_error(s, m, "No Conference name provided.");
3507                 return 0;
3508         }
3509         if (ast_strlen_zero(channel_name)) {
3510                 astman_send_error(s, m, "No channel name provided.");
3511                 return 0;
3512         }
3513         if (!ao2_container_count(conference_bridges)) {
3514                 astman_send_error(s, m, "No active conferences.");
3515                 return 0;
3516         }
3517
3518         res = generic_mute_unmute_helper(mute, conference_name, channel_name);
3519
3520         if (res == -1) {
3521                 astman_send_error(s, m, "No Conference by that name found.");
3522                 return 0;
3523         } else if (res == -2) {
3524                 astman_send_error(s, m, "No Channel by that name found in Conference.");
3525                 return 0;
3526         }
3527
3528         astman_send_ack(s, m, mute ? "User muted" : "User unmuted");
3529         return 0;
3530 }
3531
3532 static int action_confbridgeunmute(struct mansession *s, const struct message *m)
3533 {
3534         return action_mute_unmute_helper(s, m, 0);
3535 }
3536 static int action_confbridgemute(struct mansession *s, const struct message *m)
3537 {
3538         return action_mute_unmute_helper(s, m, 1);
3539 }
3540
3541 static int action_lock_unlock_helper(struct mansession *s, const struct message *m, int lock)
3542 {
3543         const char *conference_name = astman_get_header(m, "Conference");
3544         int res = 0;
3545
3546         if (ast_strlen_zero(conference_name)) {
3547                 astman_send_error(s, m, "No Conference name provided.");
3548                 return 0;
3549         }
3550         if (!ao2_container_count(conference_bridges)) {
3551                 astman_send_error(s, m, "No active conferences.");
3552                 return 0;
3553         }
3554         if ((res = generic_lock_unlock_helper(lock, conference_name))) {
3555                 astman_send_error(s, m, "No Conference by that name found.");
3556                 return 0;
3557         }
3558         astman_send_ack(s, m, lock ? "Conference locked" : "Conference unlocked");
3559         return 0;
3560 }
3561 static int action_confbridgeunlock(struct mansession *s, const struct message *m)
3562 {
3563         return action_lock_unlock_helper(s, m, 0);
3564 }
3565 static int action_confbridgelock(struct mansession *s, const struct message *m)
3566 {
3567         return action_lock_unlock_helper(s, m, 1);
3568 }
3569
3570 static int action_confbridgekick(struct mansession *s, const struct message *m)
3571 {
3572         const char *conference_name = astman_get_header(m, "Conference");
3573         const char *channel = astman_get_header(m, "Channel");
3574         struct confbridge_conference *conference;
3575         int found;
3576
3577         if (ast_strlen_zero(conference_name)) {
3578                 astman_send_error(s, m, "No Conference name provided.");
3579                 return 0;
3580         }
3581         if (!ao2_container_count(conference_bridges)) {
3582                 astman_send_error(s, m, "No active conferences.");
3583                 return 0;
3584         }
3585
3586         conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
3587         if (!conference) {
3588                 astman_send_error(s, m, "No Conference by that name found.");
3589                 return 0;
3590         }
3591
3592         found = !kick_conference_participant(conference, channel);
3593         ao2_ref(conference, -1);
3594
3595         if (found) {
3596                 astman_send_ack(s, m, !strcmp("all", channel) ? "All participants kicked" : "User kicked");
3597         } else {
3598                 astman_send_error(s, m, "No Channel by that name found in Conference.");
3599         }
3600         return 0;
3601 }
3602
3603 static int action_confbridgestartrecord(struct mansession *s, const struct message *m)
3604 {
3605         const char *conference_name = astman_get_header(m, "Conference");
3606         const char *recordfile = astman_get_header(m, "RecordFile");
3607         struct confbridge_conference *conference;
3608
3609         if (ast_strlen_zero(conference_name)) {
3610                 astman_send_error(s, m, "No Conference name provided.");
3611                 return 0;
3612         }
3613         if (!ao2_container_count(conference_bridges)) {
3614                 astman_send_error(s, m, "No active conferences.");
3615                 return 0;
3616         }
3617
3618         conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
3619         if (!conference) {
3620                 astman_send_error(s, m, "No Conference by that name found.");
3621                 return 0;
3622         }
3623
3624         ao2_lock(conference);
3625         if (conf_is_recording(conference)) {
3626                 astman_send_error(s, m, "Conference is already being recorded.");
3627                 ao2_unlock(conference);
3628                 ao2_ref(conference, -1);
3629                 return 0;
3630         }
3631
3632         if (!ast_strlen_zero(recordfile)) {
3633                 ast_copy_string(conference->b_profile.rec_file, recordfile, sizeof(conference->b_profile.rec_file));
3634         }
3635
3636         if (conf_start_record(conference)) {
3637                 astman_send_error(s, m, "Internal error starting conference recording.");
3638                 ao2_unlock(conference);
3639                 ao2_ref(conference, -1);
3640                 return 0;
3641         }
3642         ao2_unlock(conference);
3643
3644         ao2_ref(conference, -1);
3645         astman_send_ack(s, m, "Conference Recording Started.");
3646         return 0;
3647 }
3648 static int action_confbridgestoprecord(struct mansession *s, const struct message *m)
3649 {
3650         const char *conference_name = astman_get_header(