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