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