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