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