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