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