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