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