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