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