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