A great big renaming patch
[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);
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 *pvt_data, int talking)
1406 {
1407         const char *conf_name = pvt_data;
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         }
1591
1592         /* Set dsp threshold values if present */
1593         if (user.u_profile.talking_threshold) {
1594                 user.tech_args.talking_threshold = user.u_profile.talking_threshold;
1595         }
1596         if (user.u_profile.silence_threshold) {
1597                 user.tech_args.silence_threshold = user.u_profile.silence_threshold;
1598         }
1599
1600         /* Set a talker indicate call back if talking detection is requested */
1601         if (ast_test_flag(&user.u_profile, USER_OPT_TALKER_DETECT)) {
1602                 char *conf_name = ast_strdup(args.conf_name); /* this is freed during feature cleanup */
1603
1604                 if (!conf_name) {
1605                         res = -1; /* invalid PIN */
1606                         goto confbridge_cleanup;
1607                 }
1608                 if (ast_bridge_talk_detector_hook(&user.features, conf_handle_talker_cb,
1609                         conf_name, conf_handle_talker_destructor, AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
1610                         ast_free(conf_name);
1611                         res = -1;
1612                         goto confbridge_cleanup;
1613                 }
1614         }
1615
1616         /* Look for a conference bridge matching the provided name */
1617         if (!(conference = join_conference_bridge(args.conf_name, &user))) {
1618                 res = -1; /* invalid PIN */
1619                 goto confbridge_cleanup;
1620         }
1621
1622         /* Keep a copy of volume adjustments so we can restore them later if need be */
1623         volume_adjustments[0] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_READ);
1624         volume_adjustments[1] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_WRITE);
1625
1626         /* If the caller should be joined already muted, make it so */
1627         if (ast_test_flag(&user.u_profile, USER_OPT_STARTMUTED)) {
1628                 user.features.mute = 1;
1629         }
1630
1631         if (ast_test_flag(&user.u_profile, USER_OPT_DROP_SILENCE)) {
1632                 user.tech_args.drop_silence = 1;
1633         }
1634
1635         if (ast_test_flag(&user.u_profile, USER_OPT_JITTERBUFFER)) {
1636                 char *func_jb;
1637                 if ((func_jb = ast_module_helper("", "func_jitterbuffer", 0, 0, 0, 0))) {
1638                         ast_free(func_jb);
1639                         ast_func_write(chan, "JITTERBUFFER(adaptive)", "default");
1640                 }
1641         }
1642
1643         if (ast_test_flag(&user.u_profile, USER_OPT_DENOISE)) {
1644                 char *mod_speex;
1645                 /* Reduce background noise from each participant */
1646                 if ((mod_speex = ast_module_helper("", "codec_speex", 0, 0, 0, 0))) {
1647                         ast_free(mod_speex);
1648                         ast_func_write(chan, "DENOISE(rx)", "on");
1649                 }
1650         }
1651
1652         /* if this user has a intro, play it before entering */
1653         if (!ast_strlen_zero(user.name_rec_location)) {
1654                 ast_autoservice_start(chan);
1655                 play_sound_file(conference, user.name_rec_location);
1656                 play_sound_file(conference,
1657                         conf_get_sound(CONF_SOUND_HAS_JOINED, user.b_profile.sounds));
1658                 ast_autoservice_stop(chan);
1659         }
1660
1661         /* Play the Join sound to both the conference and the user entering. */
1662         if (!quiet) {
1663                 const char *join_sound = conf_get_sound(CONF_SOUND_JOIN, user.b_profile.sounds);
1664
1665                 ast_stream_and_wait(chan, join_sound, "");
1666                 ast_autoservice_start(chan);
1667                 play_sound_file(conference, join_sound);
1668                 ast_autoservice_stop(chan);
1669         }
1670
1671         /* See if we need to automatically set this user as a video source or not */
1672         handle_video_on_join(conference, user.chan, ast_test_flag(&user.u_profile, USER_OPT_MARKEDUSER));
1673
1674         conf_moh_unsuspend(&user);
1675
1676         /* Join our conference bridge for real */
1677         send_join_event(user.chan, conference);
1678         ast_bridge_join(conference->bridge,
1679                 chan,
1680                 NULL,
1681                 &user.features,
1682                 &user.tech_args,
1683                 0);
1684         send_leave_event(user.chan, conference);
1685
1686         /* if we're shutting down, don't attempt to do further processing */
1687         if (ast_shutting_down()) {
1688                 leave_conference(&user);
1689                 conference = NULL;
1690                 goto confbridge_cleanup;
1691         }
1692
1693         /* If this user was a video source, we need to clean up and possibly pick a new source. */
1694         handle_video_on_exit(conference, user.chan);
1695
1696         /* if this user has a intro, play it when leaving */
1697         if (!quiet && !ast_strlen_zero(user.name_rec_location)) {
1698                 ast_autoservice_start(chan);
1699                 play_sound_file(conference, user.name_rec_location);
1700                 play_sound_file(conference,
1701                         conf_get_sound(CONF_SOUND_HAS_LEFT, user.b_profile.sounds));
1702                 ast_autoservice_stop(chan);
1703         }
1704
1705         /* play the leave sound */
1706         if (!quiet) {
1707                 const char *leave_sound = conf_get_sound(CONF_SOUND_LEAVE, user.b_profile.sounds);
1708                 ast_autoservice_start(chan);
1709                 play_sound_file(conference, leave_sound);
1710                 ast_autoservice_stop(chan);
1711         }
1712
1713         /* Easy as pie, depart this channel from the conference bridge */
1714         leave_conference(&user);
1715         conference = NULL;
1716
1717         /* If the user was kicked from the conference play back the audio prompt for it */
1718         if (!quiet && user.kicked) {
1719                 res = ast_stream_and_wait(chan,
1720                         conf_get_sound(CONF_SOUND_KICKED, user.b_profile.sounds),
1721                         "");
1722         }
1723
1724         /* Restore volume adjustments to previous values in case they were changed */
1725         if (volume_adjustments[0]) {
1726                 ast_audiohook_volume_set(chan, AST_AUDIOHOOK_DIRECTION_READ, volume_adjustments[0]);
1727         }
1728         if (volume_adjustments[1]) {
1729                 ast_audiohook_volume_set(chan, AST_AUDIOHOOK_DIRECTION_WRITE, volume_adjustments[1]);
1730         }
1731
1732         if (!ast_strlen_zero(user.name_rec_location)) {
1733                 ast_filedelete(user.name_rec_location, NULL);
1734         }
1735
1736 confbridge_cleanup:
1737         ast_bridge_features_cleanup(&user.features);
1738         conf_bridge_profile_destroy(&user.b_profile);
1739         return res;
1740 }
1741
1742 static int action_toggle_mute(struct confbridge_conference *conference,
1743         struct confbridge_user *user,
1744         struct ast_channel *chan)
1745 {
1746         /* Mute or unmute yourself, note we only allow manipulation if they aren't waiting for a marked user or if marked users exist */
1747         if (!ast_test_flag(&user->u_profile, USER_OPT_WAITMARKED) || conference->markedusers) {
1748                 user->features.mute = (!user->features.mute ? 1 : 0);
1749                 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));
1750                 if (user->features.mute) {
1751                         send_mute_event(chan, conference);
1752                 } else {
1753                         send_unmute_event(chan, conference);
1754                 }
1755         }
1756         return ast_stream_and_wait(chan, (user->features.mute ?
1757                 conf_get_sound(CONF_SOUND_MUTED, user->b_profile.sounds) :
1758                 conf_get_sound(CONF_SOUND_UNMUTED, user->b_profile.sounds)),
1759                 "");
1760 }
1761
1762 static int action_toggle_mute_participants(struct confbridge_conference *conference, struct confbridge_user *user)
1763 {
1764         struct confbridge_user *cur_user = NULL;
1765         const char *sound_to_play;
1766
1767         ao2_lock(conference);
1768
1769         /* If already muted, then unmute */
1770         conference->muted = conference->muted ? 0 : 1;
1771         sound_to_play = conf_get_sound((conference->muted ? CONF_SOUND_PARTICIPANTS_MUTED : CONF_SOUND_PARTICIPANTS_UNMUTED),
1772                 user->b_profile.sounds);
1773
1774         AST_LIST_TRAVERSE(&conference->active_list, cur_user, list) {
1775                 if (!ast_test_flag(&cur_user->u_profile, USER_OPT_ADMIN)) {
1776                         cur_user->features.mute = conference->muted;
1777                 }
1778         }
1779
1780         ao2_unlock(conference);
1781
1782         /* The host needs to hear it seperately, as they don't get the audio from play_sound_helper */
1783         ast_stream_and_wait(user->chan, sound_to_play, "");
1784
1785         /* Announce to the group that all participants are muted */
1786         ast_autoservice_start(user->chan);
1787         play_sound_helper(conference, sound_to_play, 0);
1788         ast_autoservice_stop(user->chan);
1789
1790         return 0;
1791 }
1792
1793 static int action_playback(struct ast_bridge_channel *bridge_channel, const char *playback_file)
1794 {
1795         char *file_copy = ast_strdupa(playback_file);
1796         char *file = NULL;
1797
1798         while ((file = strsep(&file_copy, "&"))) {
1799                 if (ast_stream_and_wait(bridge_channel->chan, file, "")) {
1800                         ast_log(LOG_WARNING, "Failed to playback file %s to channel\n", file);
1801                         return -1;
1802                 }
1803         }
1804         return 0;
1805 }
1806
1807 static int action_playback_and_continue(struct confbridge_conference *conference,
1808         struct confbridge_user *user,
1809         struct ast_bridge_channel *bridge_channel,
1810         struct conf_menu *menu,
1811         const char *playback_file,
1812         const char *cur_dtmf,
1813         int *stop_prompts)
1814 {
1815         int i;
1816         int digit = 0;
1817         char dtmf[MAXIMUM_DTMF_FEATURE_STRING];
1818         struct conf_menu_entry new_menu_entry = { { 0, }, };
1819         char *file_copy = ast_strdupa(playback_file);
1820         char *file = NULL;
1821
1822         while ((file = strsep(&file_copy, "&"))) {
1823                 if (ast_streamfile(bridge_channel->chan, file, ast_channel_language(bridge_channel->chan))) {
1824                         ast_log(LOG_WARNING, "Failed to playback file %s to channel\n", file);
1825                         return -1;
1826                 }
1827
1828                 /* now wait for more digits. */
1829                 if (!(digit = ast_waitstream(bridge_channel->chan, AST_DIGIT_ANY))) {
1830                         /* streaming finished and no DTMF was entered */
1831                         continue;
1832                 } else if (digit == -1) {
1833                         /* error */
1834                         return -1;
1835                 } else {
1836                         break; /* dtmf was entered */
1837                 }
1838         }
1839         if (!digit) {
1840                 /* streaming finished on all files and no DTMF was entered */
1841                 return -1;
1842         }
1843         ast_stopstream(bridge_channel->chan);
1844
1845         /* If we get here, then DTMF has been entered, This means no
1846          * additional prompts should be played for this menu entry */
1847         *stop_prompts = 1;
1848
1849         /* If a digit was pressed during the payback, update
1850          * the dtmf string and look for a new menu entry in the
1851          * menu structure */
1852         ast_copy_string(dtmf, cur_dtmf, sizeof(dtmf));
1853         for (i = 0; i < (MAXIMUM_DTMF_FEATURE_STRING - 1); i++) {
1854                 dtmf[i] = cur_dtmf[i];
1855                 if (!dtmf[i]) {
1856                         dtmf[i] = (char) digit;
1857                         dtmf[i + 1] = '\0';
1858                         i = -1;
1859                         break;
1860                 }
1861         }
1862         /* If i is not -1 then the new dtmf digit was _NOT_ added to the string.
1863          * If this is the case, no new DTMF sequence should be looked for. */
1864         if (i != -1) {
1865                 return 0;
1866         }
1867
1868         if (conf_find_menu_entry_by_sequence(dtmf, menu, &new_menu_entry)) {
1869                 execute_menu_entry(conference,
1870                         user,
1871                         bridge_channel,
1872                         &new_menu_entry, menu);
1873                 conf_menu_entry_destroy(&new_menu_entry);
1874         }
1875         return 0;
1876 }
1877
1878 static int action_kick_last(struct confbridge_conference *conference,
1879         struct ast_bridge_channel *bridge_channel,
1880         struct confbridge_user *user)
1881 {
1882         struct confbridge_user *last_user = NULL;
1883         int isadmin = ast_test_flag(&user->u_profile, USER_OPT_ADMIN);
1884
1885         if (!isadmin) {
1886                 ast_stream_and_wait(bridge_channel->chan,
1887                         conf_get_sound(CONF_SOUND_ERROR_MENU, user->b_profile.sounds),
1888                         "");
1889                 ast_log(LOG_WARNING, "Only admin users can use the kick_last menu action. Channel %s of conf %s is not an admin.\n",
1890                         ast_channel_name(bridge_channel->chan),
1891                         conference->name);
1892                 return -1;
1893         }
1894
1895         ao2_lock(conference);
1896         if (((last_user = AST_LIST_LAST(&conference->active_list)) == user)
1897                 || (ast_test_flag(&last_user->u_profile, USER_OPT_ADMIN))) {
1898                 ao2_unlock(conference);
1899                 ast_stream_and_wait(bridge_channel->chan,
1900                         conf_get_sound(CONF_SOUND_ERROR_MENU, user->b_profile.sounds),
1901                         "");
1902         } else if (last_user) {
1903                 last_user->kicked = 1;
1904                 ast_bridge_remove(conference->bridge, last_user->chan);
1905                 ao2_unlock(conference);
1906         }
1907         return 0;
1908 }
1909
1910 static int action_dialplan_exec(struct ast_bridge_channel *bridge_channel, struct conf_menu_action *menu_action)
1911 {
1912         struct ast_pbx_args args;
1913         struct ast_pbx *pbx;
1914         char *exten;
1915         char *context;
1916         int priority;
1917         int res;
1918
1919         memset(&args, 0, sizeof(args));
1920         args.no_hangup_chan = 1;
1921
1922         ast_channel_lock(bridge_channel->chan);
1923
1924         /*save off*/
1925         exten = ast_strdupa(ast_channel_exten(bridge_channel->chan));
1926         context = ast_strdupa(ast_channel_context(bridge_channel->chan));
1927         priority = ast_channel_priority(bridge_channel->chan);
1928         pbx = ast_channel_pbx(bridge_channel->chan);
1929         ast_channel_pbx_set(bridge_channel->chan, NULL);
1930
1931         /*set new*/
1932         ast_channel_exten_set(bridge_channel->chan, menu_action->data.dialplan_args.exten);
1933         ast_channel_context_set(bridge_channel->chan, menu_action->data.dialplan_args.context);
1934         ast_channel_priority_set(bridge_channel->chan, menu_action->data.dialplan_args.priority);
1935
1936         ast_channel_unlock(bridge_channel->chan);
1937
1938         /*execute*/
1939         res = ast_pbx_run_args(bridge_channel->chan, &args);
1940
1941         /*restore*/
1942         ast_channel_lock(bridge_channel->chan);
1943
1944         ast_channel_exten_set(bridge_channel->chan, exten);
1945         ast_channel_context_set(bridge_channel->chan, context);
1946         ast_channel_priority_set(bridge_channel->chan, priority);
1947         ast_channel_pbx_set(bridge_channel->chan, pbx);
1948
1949         ast_channel_unlock(bridge_channel->chan);
1950
1951         return res;
1952 }
1953
1954 static int execute_menu_entry(struct confbridge_conference *conference,
1955         struct confbridge_user *user,
1956         struct ast_bridge_channel *bridge_channel,
1957         struct conf_menu_entry *menu_entry,
1958         struct conf_menu *menu)
1959 {
1960         struct conf_menu_action *menu_action;
1961         int isadmin = ast_test_flag(&user->u_profile, USER_OPT_ADMIN);
1962         int stop_prompts = 0;
1963         int res = 0;
1964
1965         AST_LIST_TRAVERSE(&menu_entry->actions, menu_action, action) {
1966                 switch (menu_action->id) {
1967                 case MENU_ACTION_TOGGLE_MUTE:
1968                         res |= action_toggle_mute(conference,
1969                                 user,
1970                                 bridge_channel->chan);
1971                         break;
1972                 case MENU_ACTION_ADMIN_TOGGLE_MUTE_PARTICIPANTS:
1973                         if (!isadmin) {
1974                                 break;
1975                         }
1976                         action_toggle_mute_participants(conference, user);
1977                         break;
1978                 case MENU_ACTION_PARTICIPANT_COUNT:
1979                         announce_user_count(conference, user);
1980                         break;
1981                 case MENU_ACTION_PLAYBACK:
1982                         if (!stop_prompts) {
1983                                 res |= action_playback(bridge_channel, menu_action->data.playback_file);
1984                         }
1985                         break;
1986                 case MENU_ACTION_RESET_LISTENING:
1987                         ast_audiohook_volume_set(user->chan, AST_AUDIOHOOK_DIRECTION_WRITE, 0);
1988                         break;
1989                 case MENU_ACTION_RESET_TALKING:
1990                         ast_audiohook_volume_set(user->chan, AST_AUDIOHOOK_DIRECTION_READ, 0);
1991                         break;
1992                 case MENU_ACTION_INCREASE_LISTENING:
1993                         ast_audiohook_volume_adjust(user->chan,
1994                                 AST_AUDIOHOOK_DIRECTION_WRITE, 1);
1995                         break;
1996                 case MENU_ACTION_DECREASE_LISTENING:
1997                         ast_audiohook_volume_adjust(user->chan,
1998                                 AST_AUDIOHOOK_DIRECTION_WRITE, -1);
1999                         break;
2000                 case MENU_ACTION_INCREASE_TALKING:
2001                         ast_audiohook_volume_adjust(user->chan,
2002                                 AST_AUDIOHOOK_DIRECTION_READ, 1);
2003                         break;
2004                 case MENU_ACTION_DECREASE_TALKING:
2005                         ast_audiohook_volume_adjust(user->chan,
2006                                 AST_AUDIOHOOK_DIRECTION_READ, -1);
2007                         break;
2008                 case MENU_ACTION_PLAYBACK_AND_CONTINUE:
2009                         if (!(stop_prompts)) {
2010                                 res |= action_playback_and_continue(conference,
2011                                         user,
2012                                         bridge_channel,
2013                                         menu,
2014                                         menu_action->data.playback_file,
2015                                         menu_entry->dtmf,
2016                                         &stop_prompts);
2017                         }
2018                         break;
2019                 case MENU_ACTION_DIALPLAN_EXEC:
2020                         res |= action_dialplan_exec(bridge_channel, menu_action);
2021                         break;
2022                 case MENU_ACTION_ADMIN_TOGGLE_LOCK:
2023                         if (!isadmin) {
2024                                 break;
2025                         }
2026                         conference->locked = (!conference->locked ? 1 : 0);
2027                         res |= ast_stream_and_wait(bridge_channel->chan,
2028                                 (conference->locked ?
2029                                 conf_get_sound(CONF_SOUND_LOCKED_NOW, user->b_profile.sounds) :
2030                                 conf_get_sound(CONF_SOUND_UNLOCKED_NOW, user->b_profile.sounds)),
2031                                 "");
2032
2033                         break;
2034                 case MENU_ACTION_ADMIN_KICK_LAST:
2035                         res |= action_kick_last(conference, bridge_channel, user);
2036                         break;
2037                 case MENU_ACTION_LEAVE:
2038                         ao2_lock(conference);
2039                         ast_bridge_remove(conference->bridge, bridge_channel->chan);
2040                         ao2_unlock(conference);
2041                         break;
2042                 case MENU_ACTION_NOOP:
2043                         break;
2044                 case MENU_ACTION_SET_SINGLE_VIDEO_SRC:
2045                         ao2_lock(conference);
2046                         ast_bridge_set_single_src_video_mode(conference->bridge, bridge_channel->chan);
2047                         ao2_unlock(conference);
2048                         break;
2049                 case MENU_ACTION_RELEASE_SINGLE_VIDEO_SRC:
2050                         handle_video_on_exit(conference, bridge_channel->chan);
2051                         break;
2052                 }
2053         }
2054         return res;
2055 }
2056
2057 int conf_handle_dtmf(struct ast_bridge_channel *bridge_channel,
2058         struct confbridge_user *user,
2059         struct conf_menu_entry *menu_entry,
2060         struct conf_menu *menu)
2061 {
2062         /* See if music on hold is playing */
2063         conf_moh_suspend(user);
2064
2065         /* execute the list of actions associated with this menu entry */
2066         execute_menu_entry(user->conference, user, bridge_channel, menu_entry, menu);
2067
2068         /* See if music on hold needs to be started back up again */
2069         conf_moh_unsuspend(user);
2070
2071         return 0;
2072 }
2073
2074 static int kick_conference_participant(struct confbridge_conference *conference, const char *channel)
2075 {
2076         int res = -1;
2077         struct confbridge_user *user = NULL;
2078
2079         SCOPED_AO2LOCK(bridge_lock, conference);
2080         AST_LIST_TRAVERSE(&conference->active_list, user, list) {
2081                 if (!strcasecmp(ast_channel_name(user->chan), channel)) {
2082                         user->kicked = 1;
2083                         ast_bridge_remove(conference->bridge, user->chan);
2084                         return 0;
2085                 } else if (!strcasecmp("all", channel)) {
2086                         user->kicked = 1;
2087                         ast_bridge_remove(conference->bridge, user->chan);
2088                         res = 0;
2089                 }
2090         }
2091         AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
2092                 if (!strcasecmp(ast_channel_name(user->chan), channel)) {
2093                         user->kicked = 1;
2094                         ast_bridge_remove(conference->bridge, user->chan);
2095                         return 0;
2096                 } else if (!strcasecmp("all", channel)) {
2097                         user->kicked = 1;
2098                         ast_bridge_remove(conference->bridge, user->chan);
2099                         res = 0;
2100                 }
2101         }
2102
2103         return res;
2104 }
2105
2106 static char *complete_confbridge_name(const char *line, const char *word, int pos, int state)
2107 {
2108         int which = 0;
2109         struct confbridge_conference *conference;
2110         char *res = NULL;
2111         int wordlen = strlen(word);
2112         struct ao2_iterator iter;
2113
2114         iter = ao2_iterator_init(conference_bridges, 0);
2115         while ((conference = ao2_iterator_next(&iter))) {
2116                 if (!strncasecmp(conference->name, word, wordlen) && ++which > state) {
2117                         res = ast_strdup(conference->name);
2118                         ao2_ref(conference, -1);
2119                         break;
2120                 }
2121                 ao2_ref(conference, -1);
2122         }
2123         ao2_iterator_destroy(&iter);
2124
2125         return res;
2126 }
2127
2128 static char *complete_confbridge_participant(const char *conference_name, const char *line, const char *word, int pos, int state)
2129 {
2130         int which = 0;
2131         RAII_VAR(struct confbridge_conference *, conference, NULL, ao2_cleanup);
2132         struct confbridge_user *user;
2133         char *res = NULL;
2134         int wordlen = strlen(word);
2135
2136         conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
2137         if (!conference) {
2138                 return NULL;
2139         }
2140
2141         {
2142                 SCOPED_AO2LOCK(bridge_lock, conference);
2143                 AST_LIST_TRAVERSE(&conference->active_list, user, list) {
2144                         if (!strncasecmp(ast_channel_name(user->chan), word, wordlen) && ++which > state) {
2145                                 res = ast_strdup(ast_channel_name(user->chan));
2146                                 return res;
2147                         }
2148                 }
2149                 AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
2150                         if (!strncasecmp(ast_channel_name(user->chan), word, wordlen) && ++which > state) {
2151                                 res = ast_strdup(ast_channel_name(user->chan));
2152                                 return res;
2153                         }
2154                 }
2155         }
2156
2157         return NULL;
2158 }
2159
2160 static char *handle_cli_confbridge_kick(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2161 {
2162         struct confbridge_conference *conference;
2163
2164         switch (cmd) {
2165         case CLI_INIT:
2166                 e->command = "confbridge kick";
2167                 e->usage =
2168                         "Usage: confbridge kick <conference> <channel>\n"
2169                         "       Kicks a channel out of the conference bridge.\n";
2170                 return NULL;
2171         case CLI_GENERATE:
2172                 if (a->pos == 2) {
2173                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
2174                 }
2175                 if (a->pos == 3) {
2176                         return complete_confbridge_participant(a->argv[2], a->line, a->word, a->pos, a->n);
2177                 }
2178                 return NULL;
2179         }
2180
2181         if (a->argc != 4) {
2182                 return CLI_SHOWUSAGE;
2183         }
2184
2185         conference = ao2_find(conference_bridges, a->argv[2], OBJ_KEY);
2186         if (!conference) {
2187                 ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
2188                 return CLI_SUCCESS;
2189         }
2190         if (kick_conference_participant(conference, a->argv[3])) {
2191                 ast_cli(a->fd, "No participant named '%s' found!\n", a->argv[3]);
2192                 return CLI_SUCCESS;
2193         }
2194         ao2_ref(conference, -1);
2195         ast_cli(a->fd, "Participant '%s' kicked out of conference '%s'\n", a->argv[3], a->argv[2]);
2196         return CLI_SUCCESS;
2197 }
2198
2199 static void handle_cli_confbridge_list_item(struct ast_cli_args *a, struct confbridge_user *user, int waiting)
2200 {
2201         char flag_str[5 + 1];/* Max flags + terminator */
2202         int pos = 0;
2203
2204         /* Build flags column string. */
2205         if (ast_test_flag(&user->u_profile, USER_OPT_ADMIN)) {
2206                 flag_str[pos++] = 'A';
2207         }
2208         if (ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER)) {
2209                 flag_str[pos++] = 'M';
2210         }
2211         if (ast_test_flag(&user->u_profile, USER_OPT_WAITMARKED)) {
2212                 flag_str[pos++] = 'W';
2213         }
2214         if (ast_test_flag(&user->u_profile, USER_OPT_ENDMARKED)) {
2215                 flag_str[pos++] = 'E';
2216         }
2217         if (waiting) {
2218                 flag_str[pos++] = 'w';
2219         }
2220         flag_str[pos] = '\0';
2221
2222         ast_cli(a->fd, "%-29s ", ast_channel_name(user->chan));
2223         ast_cli(a->fd, "%-5s ", flag_str);
2224         ast_cli(a->fd, "%-17s", user->u_profile.name);
2225         ast_cli(a->fd, "%-17s", user->b_profile.name);
2226         ast_cli(a->fd, "%-17s", user->menu_name);
2227         ast_cli(a->fd, "%-17s", S_COR(ast_channel_caller(user->chan)->id.number.valid, ast_channel_caller(user->chan)->id.number.str, "<unknown>"));
2228         ast_cli(a->fd, "\n");
2229 }
2230
2231 static char *handle_cli_confbridge_list(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2232 {
2233         struct confbridge_conference *conference;
2234
2235         switch (cmd) {
2236         case CLI_INIT:
2237                 e->command = "confbridge list";
2238                 e->usage =
2239                         "Usage: confbridge list [<name>]\n"
2240                         "       Lists all currently active conference bridges or a specific conference bridge.\n"
2241                         "\n"
2242                         "       When a conference bridge name is provided, flags may be shown for users. Below\n"
2243                         "       are the flags and what they represent.\n"
2244                         "\n"
2245                         "       Flags:\n"
2246                         "         A - The user is an admin\n"
2247                         "         M - The user is a marked user\n"
2248                         "         W - The user must wait for a marked user to join\n"
2249                         "         E - The user will be kicked after the last marked user leaves the conference\n"
2250                         "         w - The user is waiting for a marked user to join\n";
2251                 return NULL;
2252         case CLI_GENERATE:
2253                 if (a->pos == 2) {
2254                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
2255                 }
2256                 return NULL;
2257         }
2258
2259         if (a->argc == 2) {
2260                 struct ao2_iterator iter;
2261
2262                 ast_cli(a->fd, "Conference Bridge Name           Users  Marked Locked?\n");
2263                 ast_cli(a->fd, "================================ ====== ====== ========\n");
2264                 iter = ao2_iterator_init(conference_bridges, 0);
2265                 while ((conference = ao2_iterator_next(&iter))) {
2266                         ast_cli(a->fd, "%-32s %6i %6i %s\n", conference->name, conference->activeusers + conference->waitingusers, conference->markedusers, (conference->locked ? "locked" : "unlocked"));
2267                         ao2_ref(conference, -1);
2268                 }
2269                 ao2_iterator_destroy(&iter);
2270                 return CLI_SUCCESS;
2271         }
2272
2273         if (a->argc == 3) {
2274                 struct confbridge_user *user;
2275
2276                 conference = ao2_find(conference_bridges, a->argv[2], OBJ_KEY);
2277                 if (!conference) {
2278                         ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
2279                         return CLI_SUCCESS;
2280                 }
2281                 ast_cli(a->fd, "Channel                       Flags User Profile     Bridge Profile   Menu             CallerID\n");
2282                 ast_cli(a->fd, "============================= ===== ================ ================ ================ ================\n");
2283                 ao2_lock(conference);
2284                 AST_LIST_TRAVERSE(&conference->active_list, user, list) {
2285                         handle_cli_confbridge_list_item(a, user, 0);
2286                 }
2287                 AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
2288                         handle_cli_confbridge_list_item(a, user, 1);
2289                 }
2290                 ao2_unlock(conference);
2291                 ao2_ref(conference, -1);
2292                 return CLI_SUCCESS;
2293         }
2294
2295         return CLI_SHOWUSAGE;
2296 }
2297
2298 /* \internal
2299  * \brief finds a conference by name and locks/unlocks.
2300  *
2301  * \retval 0 success
2302  * \retval -1 conference not found
2303  */
2304 static int generic_lock_unlock_helper(int lock, const char *conference_name)
2305 {
2306         struct confbridge_conference *conference;
2307         int res = 0;
2308
2309         conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
2310         if (!conference) {
2311                 return -1;
2312         }
2313         ao2_lock(conference);
2314         conference->locked = lock;
2315         ast_test_suite_event_notify("CONF_LOCK", "Message: conference %s\r\nConference: %s", conference->locked ? "locked" : "unlocked", conference->b_profile.name);
2316         ao2_unlock(conference);
2317         ao2_ref(conference, -1);
2318
2319         return res;
2320 }
2321
2322 /* \internal
2323  * \brief finds a conference user by channel name and mutes/unmutes them.
2324  *
2325  * \retval 0 success
2326  * \retval -1 conference not found
2327  * \retval -2 user not found
2328  */
2329 static int generic_mute_unmute_helper(int mute, const char *conference_name, const char *chan_name)
2330 {
2331         struct confbridge_conference *conference;
2332         struct confbridge_user *user;
2333         int res = 0;
2334
2335         conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
2336         if (!conference) {
2337                 return -1;
2338         }
2339         ao2_lock(conference);
2340         AST_LIST_TRAVERSE(&conference->active_list, user, list) {
2341                 if (!strncmp(chan_name, ast_channel_name(user->chan), strlen(chan_name))) {
2342                         break;
2343                 }
2344         }
2345         if (user) {
2346                 user->features.mute = mute;
2347                 ast_channel_lock(user->chan);
2348                 if (user->features.mute) {
2349                         send_mute_event(user->chan, conference);
2350                 } else {
2351                         send_unmute_event(user->chan, conference);
2352                 }
2353                 ast_channel_unlock(user->chan);
2354         } else {
2355                 res = -2;;
2356         }
2357         ao2_unlock(conference);
2358         ao2_ref(conference, -1);
2359
2360         return res;
2361 }
2362
2363 static int cli_mute_unmute_helper(int mute, struct ast_cli_args *a)
2364 {
2365         int res = generic_mute_unmute_helper(mute, a->argv[2], a->argv[3]);
2366
2367         if (res == -1) {
2368                 ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
2369                 return -1;
2370         } else if (res == -2) {
2371                 ast_cli(a->fd, "No channel named '%s' found in conference %s\n", a->argv[3], a->argv[2]);
2372                 return -1;
2373         }
2374         ast_cli(a->fd, "%s %s from confbridge %s\n", mute ? "Muting" : "Unmuting", a->argv[3], a->argv[2]);
2375         return 0;
2376 }
2377
2378 static char *handle_cli_confbridge_mute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2379 {
2380         switch (cmd) {
2381         case CLI_INIT:
2382                 e->command = "confbridge mute";
2383                 e->usage =
2384                         "Usage: confbridge mute <conference> <channel>\n"
2385                         "       Mute a channel in a conference.\n";
2386                 return NULL;
2387         case CLI_GENERATE:
2388                 if (a->pos == 2) {
2389                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
2390                 }
2391                 if (a->pos == 3) {
2392                         return complete_confbridge_participant(a->argv[2], a->line, a->word, a->pos, a->n);
2393                 }
2394                 return NULL;
2395         }
2396         if (a->argc != 4) {
2397                 return CLI_SHOWUSAGE;
2398         }
2399
2400         cli_mute_unmute_helper(1, a);
2401
2402         return CLI_SUCCESS;
2403 }
2404
2405 static char *handle_cli_confbridge_unmute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2406 {
2407         switch (cmd) {
2408         case CLI_INIT:
2409                 e->command = "confbridge unmute";
2410                 e->usage =
2411                         "Usage: confbridge unmute <conference> <channel>\n"
2412                         "       Unmute a channel in a conference.\n";
2413                 return NULL;
2414         case CLI_GENERATE:
2415                 if (a->pos == 2) {
2416                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
2417                 }
2418                 if (a->pos == 3) {
2419                         return complete_confbridge_participant(a->argv[2], a->line, a->word, a->pos, a->n);
2420                 }
2421                 return NULL;
2422         }
2423         if (a->argc != 4) {
2424                 return CLI_SHOWUSAGE;
2425         }
2426
2427         cli_mute_unmute_helper(0, a);
2428
2429         return CLI_SUCCESS;
2430 }
2431
2432 static char *handle_cli_confbridge_lock(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2433 {
2434         switch (cmd) {
2435         case CLI_INIT:
2436                 e->command = "confbridge lock";
2437                 e->usage =
2438                         "Usage: confbridge lock <conference>\n"
2439                         "       Lock a conference. While locked, no new non-admins\n"
2440                         "       may join the conference.\n";
2441                 return NULL;
2442         case CLI_GENERATE:
2443                 if (a->pos == 2) {
2444                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
2445                 }
2446                 return NULL;
2447         }
2448         if (a->argc != 3) {
2449                 return CLI_SHOWUSAGE;
2450         }
2451         if (generic_lock_unlock_helper(1, a->argv[2])) {
2452                 ast_cli(a->fd, "Conference %s is not found\n", a->argv[2]);
2453         } else {
2454                 ast_cli(a->fd, "Conference %s is locked.\n", a->argv[2]);
2455         }
2456         return CLI_SUCCESS;
2457 }
2458
2459 static char *handle_cli_confbridge_unlock(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2460 {
2461         switch (cmd) {
2462         case CLI_INIT:
2463                 e->command = "confbridge unlock";
2464                 e->usage =
2465                         "Usage: confbridge unlock <conference>\n"
2466                         "       Unlock a previously locked conference.\n";
2467                 return NULL;
2468         case CLI_GENERATE:
2469                 if (a->pos == 2) {
2470                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
2471                 }
2472                 return NULL;
2473         }
2474         if (a->argc != 3) {
2475                 return CLI_SHOWUSAGE;
2476         }
2477         if (generic_lock_unlock_helper(0, a->argv[2])) {
2478                 ast_cli(a->fd, "Conference %s is not found\n", a->argv[2]);
2479         } else {
2480                 ast_cli(a->fd, "Conference %s is unlocked.\n", a->argv[2]);
2481         }
2482         return CLI_SUCCESS;
2483 }
2484
2485 static char *handle_cli_confbridge_start_record(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2486 {
2487         const char *rec_file = NULL;
2488         struct confbridge_conference *conference;
2489
2490         switch (cmd) {
2491         case CLI_INIT:
2492                 e->command = "confbridge record start";
2493                 e->usage =
2494                         "Usage: confbridge record start <conference> <file>\n"
2495                         "       <file> is optional, Otherwise the bridge profile\n"
2496                         "       record file will be used.  If the bridge profile\n"
2497                         "       has no record file specified, a file will automatically\n"
2498                         "       be generated in the monitor directory\n";
2499                 return NULL;
2500         case CLI_GENERATE:
2501                 if (a->pos == 3) {
2502                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
2503                 }
2504                 return NULL;
2505         }
2506         if (a->argc < 4) {
2507                 return CLI_SHOWUSAGE;
2508         }
2509         if (a->argc == 5) {
2510                 rec_file = a->argv[4];
2511         }
2512
2513         conference = ao2_find(conference_bridges, a->argv[3], OBJ_KEY);
2514         if (!conference) {
2515                 ast_cli(a->fd, "Conference not found.\n");
2516                 return CLI_FAILURE;
2517         }
2518         ao2_lock(conference);
2519         if (conf_is_recording(conference)) {
2520                 ast_cli(a->fd, "Conference is already being recorded.\n");
2521                 ao2_unlock(conference);
2522                 ao2_ref(conference, -1);
2523                 return CLI_SUCCESS;
2524         }
2525         if (!ast_strlen_zero(rec_file)) {
2526                 ast_copy_string(conference->b_profile.rec_file, rec_file, sizeof(conference->b_profile.rec_file));
2527         }
2528
2529         if (start_conf_record_thread(conference)) {
2530                 ast_cli(a->fd, "Could not start recording due to internal error.\n");
2531                 ao2_unlock(conference);
2532                 ao2_ref(conference, -1);
2533                 return CLI_FAILURE;
2534         }
2535         ao2_unlock(conference);
2536
2537         ast_cli(a->fd, "Recording started\n");
2538         ao2_ref(conference, -1);
2539         return CLI_SUCCESS;
2540 }
2541
2542 static char *handle_cli_confbridge_stop_record(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2543 {
2544         struct confbridge_conference *conference;
2545         int ret;
2546
2547         switch (cmd) {
2548         case CLI_INIT:
2549                 e->command = "confbridge record stop";
2550                 e->usage =
2551                         "Usage: confbridge record stop <conference>\n"
2552                         "       Stop a previously started recording.\n";
2553                 return NULL;
2554         case CLI_GENERATE:
2555                 if (a->pos == 3) {
2556                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
2557                 }
2558                 return NULL;
2559         }
2560         if (a->argc != 4) {
2561                 return CLI_SHOWUSAGE;
2562         }
2563
2564         conference = ao2_find(conference_bridges, a->argv[3], OBJ_KEY);
2565         if (!conference) {
2566                 ast_cli(a->fd, "Conference not found.\n");
2567                 return CLI_SUCCESS;
2568         }
2569         ao2_lock(conference);
2570         ret = conf_stop_record(conference);
2571         ao2_unlock(conference);
2572         ast_cli(a->fd, "Recording %sstopped.\n", ret ? "could not be " : "");
2573         ao2_ref(conference, -1);
2574         return CLI_SUCCESS;
2575 }
2576
2577 static struct ast_cli_entry cli_confbridge[] = {
2578         AST_CLI_DEFINE(handle_cli_confbridge_list, "List conference bridges and participants."),
2579         AST_CLI_DEFINE(handle_cli_confbridge_kick, "Kick participants out of conference bridges."),
2580         AST_CLI_DEFINE(handle_cli_confbridge_mute, "Mute a participant."),
2581         AST_CLI_DEFINE(handle_cli_confbridge_unmute, "Unmute a participant."),
2582         AST_CLI_DEFINE(handle_cli_confbridge_lock, "Lock a conference."),
2583         AST_CLI_DEFINE(handle_cli_confbridge_unlock, "Unlock a conference."),
2584         AST_CLI_DEFINE(handle_cli_confbridge_start_record, "Start recording a conference"),
2585         AST_CLI_DEFINE(handle_cli_confbridge_stop_record, "Stop recording a conference."),
2586 };
2587 static struct ast_custom_function confbridge_function = {
2588         .name = "CONFBRIDGE",
2589         .write = func_confbridge_helper,
2590 };
2591
2592 static int func_confbridge_info(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len);
2593 static struct ast_custom_function confbridge_info_function = {
2594         .name = "CONFBRIDGE_INFO",
2595         .read = func_confbridge_info,
2596 };
2597
2598 static void action_confbridgelist_item(struct mansession *s, const char *id_text, struct confbridge_conference *conference, struct confbridge_user *user, int waiting)
2599 {
2600         astman_append(s,
2601                 "Event: ConfbridgeList\r\n"
2602                 "%s"
2603                 "Conference: %s\r\n"
2604                 "CallerIDNum: %s\r\n"
2605                 "CallerIDName: %s\r\n"
2606                 "Channel: %s\r\n"
2607                 "Admin: %s\r\n"
2608                 "MarkedUser: %s\r\n"
2609                 "WaitMarked: %s\r\n"
2610                 "EndMarked: %s\r\n"
2611                 "Waiting: %s\r\n"
2612                 "\r\n",
2613                 id_text,
2614                 conference->name,
2615                 S_COR(ast_channel_caller(user->chan)->id.number.valid, ast_channel_caller(user->chan)->id.number.str, "<unknown>"),
2616                 S_COR(ast_channel_caller(user->chan)->id.name.valid, ast_channel_caller(user->chan)->id.name.str, "<no name>"),
2617                 ast_channel_name(user->chan),
2618                 ast_test_flag(&user->u_profile, USER_OPT_ADMIN) ? "Yes" : "No",
2619                 ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER) ? "Yes" : "No",
2620                 ast_test_flag(&user->u_profile, USER_OPT_WAITMARKED) ? "Yes" : "No",
2621                 ast_test_flag(&user->u_profile, USER_OPT_ENDMARKED) ? "Yes" : "No",
2622                 waiting ? "Yes" : "No");
2623 }
2624
2625 static int action_confbridgelist(struct mansession *s, const struct message *m)
2626 {
2627         const char *actionid = astman_get_header(m, "ActionID");
2628         const char *conference_name = astman_get_header(m, "Conference");
2629         struct confbridge_user *user;
2630         struct confbridge_conference *conference;
2631         char id_text[80];
2632         int total = 0;
2633
2634         id_text[0] = '\0';
2635         if (!ast_strlen_zero(actionid)) {
2636                 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", actionid);
2637         }
2638         if (ast_strlen_zero(conference_name)) {
2639                 astman_send_error(s, m, "No Conference name provided.");
2640                 return 0;
2641         }
2642         if (!ao2_container_count(conference_bridges)) {
2643                 astman_send_error(s, m, "No active conferences.");
2644                 return 0;
2645         }
2646         conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
2647         if (!conference) {
2648                 astman_send_error(s, m, "No Conference by that name found.");
2649                 return 0;
2650         }
2651
2652         astman_send_listack(s, m, "Confbridge user list will follow", "start");
2653
2654         ao2_lock(conference);
2655         AST_LIST_TRAVERSE(&conference->active_list, user, list) {
2656                 total++;
2657                 action_confbridgelist_item(s, id_text, conference, user, 0);
2658         }
2659         AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
2660                 total++;
2661                 action_confbridgelist_item(s, id_text, conference, user, 1);
2662         }
2663         ao2_unlock(conference);
2664         ao2_ref(conference, -1);
2665
2666         astman_append(s,
2667         "Event: ConfbridgeListComplete\r\n"
2668         "EventList: Complete\r\n"
2669         "ListItems: %d\r\n"
2670         "%s"
2671         "\r\n", total, id_text);
2672
2673         return 0;
2674 }
2675
2676 static int action_confbridgelistrooms(struct mansession *s, const struct message *m)
2677 {
2678         const char *actionid = astman_get_header(m, "ActionID");
2679         struct confbridge_conference *conference;
2680         struct ao2_iterator iter;
2681         char id_text[512] = "";
2682         int totalitems = 0;
2683
2684         if (!ast_strlen_zero(actionid)) {
2685                 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", actionid);
2686         }
2687
2688         if (!ao2_container_count(conference_bridges)) {
2689                 astman_send_error(s, m, "No active conferences.");
2690                 return 0;
2691         }
2692
2693         astman_send_listack(s, m, "Confbridge conferences will follow", "start");
2694
2695         /* Traverse the conference list */
2696         iter = ao2_iterator_init(conference_bridges, 0);
2697         while ((conference = ao2_iterator_next(&iter))) {
2698                 totalitems++;
2699
2700                 ao2_lock(conference);
2701                 astman_append(s,
2702                 "Event: ConfbridgeListRooms\r\n"
2703                 "%s"
2704                 "Conference: %s\r\n"
2705                 "Parties: %d\r\n"
2706                 "Marked: %d\r\n"
2707                 "Locked: %s\r\n"
2708                 "\r\n",
2709                 id_text,
2710                 conference->name,
2711                 conference->activeusers + conference->waitingusers,
2712                 conference->markedusers,
2713                 conference->locked ? "Yes" : "No");
2714                 ao2_unlock(conference);
2715
2716                 ao2_ref(conference, -1);
2717         }
2718         ao2_iterator_destroy(&iter);
2719
2720         /* Send final confirmation */
2721         astman_append(s,
2722         "Event: ConfbridgeListRoomsComplete\r\n"
2723         "EventList: Complete\r\n"
2724         "ListItems: %d\r\n"
2725         "%s"
2726         "\r\n", totalitems, id_text);
2727         return 0;
2728 }
2729
2730 static int action_mute_unmute_helper(struct mansession *s, const struct message *m, int mute)
2731 {
2732         const char *conference_name = astman_get_header(m, "Conference");
2733         const char *channel_name = astman_get_header(m, "Channel");
2734         int res = 0;
2735
2736         if (ast_strlen_zero(conference_name)) {
2737                 astman_send_error(s, m, "No Conference name provided.");
2738                 return 0;
2739         }
2740         if (ast_strlen_zero(channel_name)) {
2741                 astman_send_error(s, m, "No channel name provided.");
2742                 return 0;
2743         }
2744         if (!ao2_container_count(conference_bridges)) {
2745                 astman_send_error(s, m, "No active conferences.");
2746                 return 0;
2747         }
2748
2749         res = generic_mute_unmute_helper(mute, conference_name, channel_name);
2750
2751         if (res == -1) {
2752                 astman_send_error(s, m, "No Conference by that name found.");
2753                 return 0;
2754         } else if (res == -2) {
2755                 astman_send_error(s, m, "No Channel by that name found in Conference.");
2756                 return 0;
2757         }
2758
2759         astman_send_ack(s, m, mute ? "User muted" : "User unmuted");
2760         return 0;
2761 }
2762
2763 static int action_confbridgeunmute(struct mansession *s, const struct message *m)
2764 {
2765         return action_mute_unmute_helper(s, m, 0);
2766 }
2767 static int action_confbridgemute(struct mansession *s, const struct message *m)
2768 {
2769         return action_mute_unmute_helper(s, m, 1);
2770 }
2771
2772 static int action_lock_unlock_helper(struct mansession *s, const struct message *m, int lock)
2773 {
2774         const char *conference_name = astman_get_header(m, "Conference");
2775         int res = 0;
2776
2777         if (ast_strlen_zero(conference_name)) {
2778                 astman_send_error(s, m, "No Conference name provided.");
2779                 return 0;
2780         }
2781         if (!ao2_container_count(conference_bridges)) {
2782                 astman_send_error(s, m, "No active conferences.");
2783                 return 0;
2784         }
2785         if ((res = generic_lock_unlock_helper(lock, conference_name))) {
2786                 astman_send_error(s, m, "No Conference by that name found.");
2787                 return 0;
2788         }
2789         astman_send_ack(s, m, lock ? "Conference locked" : "Conference unlocked");
2790         return 0;
2791 }
2792 static int action_confbridgeunlock(struct mansession *s, const struct message *m)
2793 {
2794         return action_lock_unlock_helper(s, m, 0);
2795 }
2796 static int action_confbridgelock(struct mansession *s, const struct message *m)
2797 {
2798         return action_lock_unlock_helper(s, m, 1);
2799 }
2800
2801 static int action_confbridgekick(struct mansession *s, const struct message *m)
2802 {
2803         const char *conference_name = astman_get_header(m, "Conference");
2804         const char *channel = astman_get_header(m, "Channel");
2805         struct confbridge_conference *conference;
2806         int found = 0;
2807
2808         if (ast_strlen_zero(conference_name)) {
2809                 astman_send_error(s, m, "No Conference name provided.");
2810                 return 0;
2811         }
2812         if (!ao2_container_count(conference_bridges)) {
2813                 astman_send_error(s, m, "No active conferences.");
2814                 return 0;
2815         }
2816
2817         conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
2818         if (!conference) {
2819                 astman_send_error(s, m, "No Conference by that name found.");
2820                 return 0;
2821         }
2822
2823         found = !kick_conference_participant(conference, channel);
2824         ao2_ref(conference, -1);
2825
2826         if (found) {
2827                 astman_send_ack(s, m, "User kicked");
2828         } else {
2829                 astman_send_error(s, m, "No Channel by that name found in Conference.");
2830         }
2831         return 0;
2832 }
2833
2834 static int action_confbridgestartrecord(struct mansession *s, const struct message *m)
2835 {
2836         const char *conference_name = astman_get_header(m, "Conference");
2837         const char *recordfile = astman_get_header(m, "RecordFile");
2838         struct confbridge_conference *conference;
2839
2840         if (ast_strlen_zero(conference_name)) {
2841                 astman_send_error(s, m, "No Conference name provided.");
2842                 return 0;
2843         }
2844         if (!ao2_container_count(conference_bridges)) {
2845                 astman_send_error(s, m, "No active conferences.");
2846                 return 0;
2847         }
2848
2849         conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
2850         if (!conference) {
2851                 astman_send_error(s, m, "No Conference by that name found.");
2852                 return 0;
2853         }
2854
2855         ao2_lock(conference);
2856         if (conf_is_recording(conference)) {
2857                 astman_send_error(s, m, "Conference is already being recorded.");
2858                 ao2_unlock(conference);
2859                 ao2_ref(conference, -1);
2860                 return 0;
2861         }
2862
2863         if (!ast_strlen_zero(recordfile)) {
2864                 ast_copy_string(conference->b_profile.rec_file, recordfile, sizeof(conference->b_profile.rec_file));
2865         }
2866
2867         if (start_conf_record_thread(conference)) {
2868                 astman_send_error(s, m, "Internal error starting conference recording.");
2869                 ao2_unlock(conference);
2870                 ao2_ref(conference, -1);
2871                 return 0;
2872         }
2873         ao2_unlock(conference);
2874
2875         ao2_ref(conference, -1);
2876         astman_send_ack(s, m, "Conference Recording Started.");
2877         return 0;
2878 }
2879 static int action_confbridgestoprecord(struct mansession *s, const struct message *m)
2880 {
2881         const char *conference_name = astman_get_header(m, "Conference");
2882         struct confbridge_conference *conference;
2883
2884         if (ast_strlen_zero(conference_name)) {
2885                 astman_send_error(s, m, "No Conference name provided.");
2886                 return 0;
2887         }
2888         if (!ao2_container_count(conference_bridges)) {
2889                 astman_send_error(s, m, "No active conferences.");
2890                 return 0;
2891         }
2892
2893         conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
2894         if (!conference) {
2895                 astman_send_error(s, m, "No Conference by that name found.");
2896                 return 0;
2897         }
2898
2899         ao2_lock(conference);
2900         if (conf_stop_record(conference)) {
2901                 ao2_unlock(conference);
2902                 astman_send_error(s, m, "Internal error while stopping recording.");
2903                 ao2_ref(conference, -1);
2904                 return 0;
2905         }
2906         ao2_unlock(conference);
2907
2908         ao2_ref(conference, -1);
2909         astman_send_ack(s, m, "Conference Recording Stopped.");
2910         return 0;
2911 }
2912
2913 static int action_confbridgesetsinglevideosrc(struct mansession *s, const struct message *m)
2914 {
2915         const char *conference_name = astman_get_header(m, "Conference");
2916         const char *channel = astman_get_header(m, "Channel");
2917         struct confbridge_user *user;
2918         struct confbridge_conference *conference;
2919
2920         if (ast_strlen_zero(conference_name)) {
2921                 astman_send_error(s, m, "No Conference name provided.");
2922                 return 0;
2923         }
2924         if (ast_strlen_zero(channel)) {
2925                 astman_send_error(s, m, "No channel name provided.");
2926                 return 0;
2927         }
2928         if (!ao2_container_count(conference_bridges)) {
2929                 astman_send_error(s, m, "No active conferences.");
2930                 return 0;
2931         }
2932
2933         conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
2934         if (!conference) {
2935                 astman_send_error(s, m, "No Conference by that name found.");
2936                 return 0;
2937         }
2938
2939         /* find channel and set as video src. */
2940         ao2_lock(conference);
2941         AST_LIST_TRAVERSE(&conference->active_list, user, list) {
2942                 if (!strncmp(channel, ast_channel_name(user->chan), strlen(channel))) {
2943                         ast_bridge_set_single_src_video_mode(conference->bridge, user->chan);
2944                         break;
2945                 }
2946         }
2947         ao2_unlock(conference);
2948         ao2_ref(conference, -1);
2949
2950         /* do not access user after conference unlock.  We are just
2951          * using this check to see if it was found or not */
2952         if (!user) {
2953                 astman_send_error(s, m, "No channel by that name found in conference.");
2954                 return 0;
2955         }
2956         astman_send_ack(s, m, "Conference single video source set.");
2957         return 0;
2958 }
2959
2960 static int func_confbridge_info(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
2961 {
2962         char *parse;
2963         struct confbridge_conference *conference;
2964         struct confbridge_user *user;
2965         int count = 0;
2966         AST_DECLARE_APP_ARGS(args,
2967                 AST_APP_ARG(type);
2968                 AST_APP_ARG(confno);
2969         );
2970
2971         /* parse all the required arguments and make sure they exist. */
2972         if (ast_strlen_zero(data)) {
2973                 return -1;
2974         }
2975         parse = ast_strdupa(data);
2976         AST_STANDARD_APP_ARGS(args, parse);
2977         if (ast_strlen_zero(args.confno) || ast_strlen_zero(args.type)) {
2978                 return -1;
2979         }
2980         conference = ao2_find(conference_bridges, args.confno, OBJ_KEY);
2981         if (!conference) {
2982                 snprintf(buf, len, "0");
2983                 return 0;
2984         }
2985
2986         /* get the correct count for the type requested */
2987         ao2_lock(conference);
2988         if (!strncasecmp(args.type, "parties", 7)) {
2989                 AST_LIST_TRAVERSE(&conference->active_list, user, list) {
2990                         count++;
2991                 }
2992                 AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
2993                         count++;
2994                 }
2995         } else if (!strncasecmp(args.type, "admins", 6)) {
2996                 AST_LIST_TRAVERSE(&conference->active_list, user, list) {
2997                         if (ast_test_flag(&user->u_profile, USER_OPT_ADMIN)) {
2998                                 count++;
2999                         }
3000                 }
3001         } else if (!strncasecmp(args.type, "marked", 6)) {
3002                 AST_LIST_TRAVERSE(&conference->active_list, user, list) {
3003                         if (ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER)) {
3004                                 count++;
3005                         }
3006                 }
3007         } else if (!strncasecmp(args.type, "locked", 6)) {
3008                 count = conference->locked;
3009         } else {
3010                 ast_log(LOG_ERROR, "Invalid keyword '%s' passed to CONFBRIDGE_INFO.  Should be one of: "
3011                         "parties, admins, marked, or locked.\n", args.type);
3012         }
3013         snprintf(buf, len, "%d", count);
3014         ao2_unlock(conference);
3015         ao2_ref(conference, -1);
3016         return 0;
3017 }
3018
3019 void conf_add_user_active(struct confbridge_conference *conference, struct confbridge_user *user)
3020 {
3021         AST_LIST_INSERT_TAIL(&conference->active_list, user, list);
3022         conference->activeusers++;
3023 }
3024
3025 void conf_add_user_marked(struct confbridge_conference *conference, struct confbridge_user *user)
3026 {
3027         AST_LIST_INSERT_TAIL(&conference->active_list, user, list);
3028         conference->activeusers++;
3029         conference->markedusers++;
3030 }
3031
3032 void conf_add_user_waiting(struct confbridge_conference *conference, struct confbridge_user *user)
3033 {
3034         AST_LIST_INSERT_TAIL(&conference->waiting_list, user, list);
3035         conference->waitingusers++;
3036 }
3037
3038 void conf_remove_user_active(struct confbridge_conference *conference, struct confbridge_user *user)
3039 {
3040         AST_LIST_REMOVE(&conference->active_list, user, list);
3041         conference->activeusers--;
3042 }
3043
3044 void conf_remove_user_marked(struct confbridge_conference *conference, struct confbridge_user *user)
3045 {
3046         AST_LIST_REMOVE(&conference->active_list, user, list);
3047         conference->activeusers--;
3048         conference->markedusers--;
3049 }
3050
3051 void conf_mute_only_active(struct confbridge_conference *conference)
3052 {
3053         struct confbridge_user *only_user = AST_LIST_FIRST(&conference->active_list);
3054
3055         /* Turn on MOH/mute if the single participant is set up for it */
3056         if (ast_test_flag(&only_user->u_profile, USER_OPT_MUSICONHOLD)) {
3057                 only_user->features.mute = 1;
3058                 conf_moh_start(only_user);
3059         }
3060 }
3061
3062 void conf_remove_user_waiting(struct confbridge_conference *conference, struct confbridge_user *user)
3063 {
3064         AST_LIST_REMOVE(&conference->waiting_list, user, list);
3065         conference->waitingusers--;
3066 }
3067
3068 /*!
3069  * \internal
3070  * \brief Unregister a ConfBridge channel technology.
3071  * \since 12.0.0
3072  *
3073  * \param tech What to unregister.
3074  *
3075  * \return Nothing
3076  */
3077 static void unregister_channel_tech(struct ast_channel_tech *tech)
3078 {
3079         ast_channel_unregister(tech);
3080         tech->capabilities = ast_format_cap_destroy(tech->capabilities);
3081 }
3082
3083 /*!
3084  * \internal
3085  * \brief Register a ConfBridge channel technology.
3086  * \since 12.0.0
3087  *
3088  * \param tech What to register.
3089  *
3090  * \retval 0 on success.
3091  * \retval -1 on error.
3092  */
3093 static int register_channel_tech(struct ast_channel_tech *tech)
3094 {
3095         tech->capabilities = ast_format_cap_alloc();
3096         if (!tech->capabilities) {
3097                 return -1;
3098         }
3099         ast_format_cap_add_all(tech->capabilities);
3100         if (ast_channel_register(tech)) {
3101                 ast_log(LOG_ERROR, "Unable to register channel technology %s(%s).\n",
3102                         tech->type, tech->description);
3103                 return -1;
3104         }
3105         return 0;
3106 }
3107
3108 /*! \brief Called when module is being unloaded */
3109 static int unload_module(void)
3110 {
3111         ast_unregister_application(app);
3112
3113         ast_custom_function_unregister(&confbridge_function);
3114         ast_custom_function_unregister(&confbridge_info_function);
3115
3116         ast_cli_unregister_multiple(cli_confbridge, ARRAY_LEN(cli_confbridge));
3117
3118         ast_manager_unregister("ConfbridgeList");
3119         ast_manager_unregister("ConfbridgeListRooms");
3120         ast_manager_unregister("ConfbridgeMute");
3121         ast_manager_unregister("ConfbridgeUnmute");
3122         ast_manager_unregister("ConfbridgeKick");
3123         ast_manager_unregister("ConfbridgeUnlock");
3124         ast_manager_unregister("ConfbridgeLock");
3125         ast_manager_unregister("ConfbridgeStartRecord");
3126         ast_manager_unregister("ConfbridgeStopRecord");
3127         ast_manager_unregister("ConfbridgeSetSingleVideoSrc");
3128
3129         /* Unsubscribe from stasis confbridge message type and clean it up. */
3130         manager_confbridge_shutdown();
3131
3132         /* Get rid of the conference bridges container. Since we only allow dynamic ones none will be active. */
3133         ao2_cleanup(conference_bridges);
3134         conference_bridges = NULL;
3135
3136         conf_destroy_config();
3137
3138         unregister_channel_tech(conf_announce_get_tech());
3139         unregister_channel_tech(conf_record_get_tech());
3140
3141         return 0;
3142 }
3143
3144 /*!
3145  * \brief Load the module
3146  *
3147  * Module loading including tests for configuration or dependencies.
3148  * This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
3149  * or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
3150  * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
3151  * configuration file or other non-critical problem return
3152  * AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
3153  */
3154 static int load_module(void)
3155 {
3156         int res = 0;
3157
3158         if (conf_load_config()) {
3159                 ast_log(LOG_ERROR, "Unable to load config. Not loading module.\n");
3160                 return AST_MODULE_LOAD_DECLINE;
3161         }
3162
3163         if (register_channel_tech(conf_record_get_tech())
3164                 || register_channel_tech(conf_announce_get_tech())) {
3165                 unload_module();
3166                 return AST_MODULE_LOAD_FAILURE;
3167         }
3168
3169         /* Create a container to hold the conference bridges */
3170         conference_bridges = ao2_container_alloc(CONFERENCE_BRIDGE_BUCKETS,
3171                 conference_bridge_hash_cb, conference_bridge_cmp_cb);
3172         if (!conference_bridges) {
3173                 unload_module();
3174                 return AST_MODULE_LOAD_FAILURE;
3175         }
3176
3177         /* Setup manager stasis subscriptions */
3178         res |= manager_confbridge_init();
3179
3180         res |= ast_register_application_xml(app, confbridge_exec);
3181
3182         res |= ast_custom_function_register(&confbridge_function);
3183         res |= ast_custom_function_register(&confbridge_info_function);
3184
3185         res |= ast_cli_register_multiple(cli_confbridge, ARRAY_LEN(cli_confbridge));
3186
3187         res |= ast_manager_register_xml("ConfbridgeList", EVENT_FLAG_REPORTING, action_confbridgelist);
3188         res |= ast_manager_register_xml("ConfbridgeListRooms", EVENT_FLAG_REPORTING, action_confbridgelistrooms);
3189         res |= ast_manager_register_xml("ConfbridgeMute", EVENT_FLAG_CALL, action_confbridgemute);
3190         res |= ast_manager_register_xml("ConfbridgeUnmute", EVENT_FLAG_CALL, action_confbridgeunmute);
3191         res |= ast_manager_register_xml("ConfbridgeKick", EVENT_FLAG_CALL, action_confbridgekick);
3192         res |= ast_manager_register_xml("ConfbridgeUnlock", EVENT_FLAG_CALL, action_confbridgeunlock);
3193         res |= ast_manager_register_xml("ConfbridgeLock", EVENT_FLAG_CALL, action_confbridgelock);
3194         res |= ast_manager_register_xml("ConfbridgeStartRecord", EVENT_FLAG_CALL, action_confbridgestartrecord);
3195         res |= ast_manager_register_xml("ConfbridgeStopRecord", EVENT_FLAG_CALL, action_confbridgestoprecord);
3196         res |= ast_manager_register_xml("ConfbridgeSetSingleVideoSrc", EVENT_FLAG_CALL, action_confbridgesetsinglevideosrc);
3197         if (res) {
3198                 unload_module();
3199                 return AST_MODULE_LOAD_FAILURE;
3200         }
3201
3202         return AST_MODULE_LOAD_SUCCESS;
3203 }
3204
3205 static int reload(void)
3206 {
3207         return conf_reload_config();
3208 }
3209
3210 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Conference Bridge Application",
3211         .load = load_module,
3212         .unload = unload_module,
3213         .reload = reload,
3214         .load_pri = AST_MODPRI_DEVSTATE_PROVIDER,
3215 );