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