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