80c84ed470d8118e42f70cc69f2a57fb74572347
[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 this user was a video source, we need to clean up and possibly pick a new source. */
1477         handle_video_on_exit(conference_bridge, conference_bridge_user.chan);
1478
1479         /* if this user has a intro, play it when leaving */
1480         if (!quiet && !ast_strlen_zero(conference_bridge_user.name_rec_location)) {
1481                 ast_autoservice_start(chan);
1482                 play_sound_file(conference_bridge, conference_bridge_user.name_rec_location);
1483                 play_sound_file(conference_bridge,
1484                         conf_get_sound(CONF_SOUND_HAS_LEFT, conference_bridge_user.b_profile.sounds));
1485                 ast_autoservice_stop(chan);
1486         }
1487
1488         /* play the leave sound */
1489         if (!quiet) {
1490                 const char *leave_sound = conf_get_sound(CONF_SOUND_LEAVE, conference_bridge_user.b_profile.sounds);
1491                 ast_autoservice_start(chan);
1492                 play_sound_file(conference_bridge, leave_sound);
1493                 ast_autoservice_stop(chan);
1494         }
1495
1496         /* Easy as pie, depart this channel from the conference bridge */
1497         leave_conference_bridge(conference_bridge, &conference_bridge_user);
1498         conference_bridge = NULL;
1499
1500         /* If the user was kicked from the conference play back the audio prompt for it */
1501         if (!quiet && conference_bridge_user.kicked) {
1502                 res = ast_stream_and_wait(chan,
1503                         conf_get_sound(CONF_SOUND_KICKED, conference_bridge_user.b_profile.sounds),
1504                         "");
1505         }
1506
1507         /* Restore volume adjustments to previous values in case they were changed */
1508         if (volume_adjustments[0]) {
1509                 ast_audiohook_volume_set(chan, AST_AUDIOHOOK_DIRECTION_READ, volume_adjustments[0]);
1510         }
1511         if (volume_adjustments[1]) {
1512                 ast_audiohook_volume_set(chan, AST_AUDIOHOOK_DIRECTION_WRITE, volume_adjustments[1]);
1513         }
1514
1515         if (!ast_strlen_zero(conference_bridge_user.name_rec_location)) {
1516                 ast_filedelete(conference_bridge_user.name_rec_location, NULL);
1517         }
1518
1519 confbridge_cleanup:
1520         ast_bridge_features_cleanup(&conference_bridge_user.features);
1521         conf_bridge_profile_destroy(&conference_bridge_user.b_profile);
1522         return res;
1523 }
1524
1525 static int action_toggle_mute(struct conference_bridge *conference_bridge,
1526         struct conference_bridge_user *conference_bridge_user,
1527         struct ast_channel *chan)
1528 {
1529         /* Mute or unmute yourself, note we only allow manipulation if they aren't waiting for a marked user or if marked users exist */
1530         if (!ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_WAITMARKED) || conference_bridge->markedusers) {
1531                 conference_bridge_user->features.mute = (!conference_bridge_user->features.mute ? 1 : 0);
1532         }
1533         return ast_stream_and_wait(chan, (conference_bridge_user->features.mute ?
1534                 conf_get_sound(CONF_SOUND_MUTED, conference_bridge_user->b_profile.sounds) :
1535                 conf_get_sound(CONF_SOUND_UNMUTED, conference_bridge_user->b_profile.sounds)),
1536                 "");
1537 }
1538
1539 static int action_playback(struct ast_bridge_channel *bridge_channel, const char *playback_file)
1540 {
1541         char *file_copy = ast_strdupa(playback_file);
1542         char *file = NULL;
1543
1544         while ((file = strsep(&file_copy, "&"))) {
1545                 if (ast_stream_and_wait(bridge_channel->chan, file, "")) {
1546                         ast_log(LOG_WARNING, "Failed to playback file %s to channel\n", file);
1547                         return -1;
1548                 }
1549         }
1550         return 0;
1551 }
1552
1553 static int action_playback_and_continue(struct conference_bridge *conference_bridge,
1554         struct conference_bridge_user *conference_bridge_user,
1555         struct ast_bridge_channel *bridge_channel,
1556         struct conf_menu *menu,
1557         const char *playback_file,
1558         const char *cur_dtmf,
1559         int *stop_prompts)
1560 {
1561         int i;
1562         int digit = 0;
1563         char dtmf[MAXIMUM_DTMF_FEATURE_STRING];
1564         struct conf_menu_entry new_menu_entry = { { 0, }, };
1565         char *file_copy = ast_strdupa(playback_file);
1566         char *file = NULL;
1567
1568         while ((file = strsep(&file_copy, "&"))) {
1569                 if (ast_streamfile(bridge_channel->chan, file, bridge_channel->chan->language)) {
1570                         ast_log(LOG_WARNING, "Failed to playback file %s to channel\n", file);
1571                         return -1;
1572                 }
1573
1574                 /* now wait for more digits. */
1575                 if (!(digit = ast_waitstream(bridge_channel->chan, AST_DIGIT_ANY))) {
1576                         /* streaming finished and no DTMF was entered */
1577                         continue;
1578                 } else if (digit == -1) {
1579                         /* error */
1580                         return -1;
1581                 } else {
1582                         break; /* dtmf was entered */
1583                 }
1584         }
1585         if (!digit) {
1586                 /* streaming finished on all files and no DTMF was entered */
1587                 return -1;
1588         }
1589         ast_stopstream(bridge_channel->chan);
1590
1591         /* If we get here, then DTMF has been entered, This means no
1592          * additional prompts should be played for this menu entry */
1593         *stop_prompts = 1;
1594
1595         /* If a digit was pressed during the payback, update
1596          * the dtmf string and look for a new menu entry in the
1597          * menu structure */
1598         ast_copy_string(dtmf, cur_dtmf, sizeof(dtmf));
1599         for (i = 0; i < (MAXIMUM_DTMF_FEATURE_STRING - 1); i++) {
1600                 dtmf[i] = cur_dtmf[i];
1601                 if (!dtmf[i]) {
1602                         dtmf[i] = (char) digit;
1603                         dtmf[i + 1] = '\0';
1604                         i = -1;
1605                         break;
1606                 }
1607         }
1608         /* If i is not -1 then the new dtmf digit was _NOT_ added to the string.
1609          * If this is the case, no new DTMF sequence should be looked for. */
1610         if (i != -1) {
1611                 return 0;
1612         }
1613
1614         if (conf_find_menu_entry_by_sequence(dtmf, menu, &new_menu_entry)) {
1615                 execute_menu_entry(conference_bridge,
1616                         conference_bridge_user,
1617                         bridge_channel,
1618                         &new_menu_entry, menu);
1619                 conf_menu_entry_destroy(&new_menu_entry);
1620         }
1621         return 0;
1622 }
1623
1624 static int action_kick_last(struct conference_bridge *conference_bridge,
1625         struct ast_bridge_channel *bridge_channel,
1626         struct conference_bridge_user *conference_bridge_user)
1627 {
1628         struct conference_bridge_user *last_participant = NULL;
1629         int isadmin = ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_ADMIN);
1630
1631         if (!isadmin) {
1632                 ast_stream_and_wait(bridge_channel->chan,
1633                         conf_get_sound(CONF_SOUND_ERROR_MENU, conference_bridge_user->b_profile.sounds),
1634                         "");
1635                 ast_log(LOG_WARNING, "Only admin users can use the kick_last menu action. Channel %s of conf %s is not an admin.\n",
1636                         bridge_channel->chan->name,
1637                         conference_bridge->name);
1638                 return -1;
1639         }
1640
1641         ao2_lock(conference_bridge);
1642         if (((last_participant = AST_LIST_LAST(&conference_bridge->users_list)) == conference_bridge_user)
1643                 || (ast_test_flag(&last_participant->u_profile, USER_OPT_ADMIN))) {
1644                 ao2_unlock(conference_bridge);
1645                 ast_stream_and_wait(bridge_channel->chan,
1646                         conf_get_sound(CONF_SOUND_ERROR_MENU, conference_bridge_user->b_profile.sounds),
1647                         "");
1648         } else if (last_participant) {
1649                 last_participant->kicked = 1;
1650                 ast_bridge_remove(conference_bridge->bridge, last_participant->chan);
1651                 ao2_unlock(conference_bridge);
1652         }
1653         return 0;
1654 }
1655
1656 static int action_dialplan_exec(struct ast_bridge_channel *bridge_channel, struct conf_menu_action *menu_action)
1657 {
1658         struct ast_pbx_args args;
1659         struct ast_pbx *pbx;
1660         char *exten;
1661         char *context;
1662         int priority;
1663         int res;
1664
1665         memset(&args, 0, sizeof(args));
1666         args.no_hangup_chan = 1;
1667
1668         ast_channel_lock(bridge_channel->chan);
1669
1670         /*save off*/
1671         exten = ast_strdupa(bridge_channel->chan->exten);
1672         context = ast_strdupa(bridge_channel->chan->context);
1673         priority = bridge_channel->chan->priority;
1674         pbx = bridge_channel->chan->pbx;
1675         bridge_channel->chan->pbx = NULL;
1676
1677         /*set new*/
1678         ast_copy_string(bridge_channel->chan->exten, menu_action->data.dialplan_args.exten, sizeof(bridge_channel->chan->exten));
1679         ast_copy_string(bridge_channel->chan->context, menu_action->data.dialplan_args.context, sizeof(bridge_channel->chan->context));
1680         bridge_channel->chan->priority = menu_action->data.dialplan_args.priority;
1681
1682         ast_channel_unlock(bridge_channel->chan);
1683
1684         /*execute*/
1685         res = ast_pbx_run_args(bridge_channel->chan, &args);
1686
1687         /*restore*/
1688         ast_channel_lock(bridge_channel->chan);
1689
1690         ast_copy_string(bridge_channel->chan->exten, exten, sizeof(bridge_channel->chan->exten));
1691         ast_copy_string(bridge_channel->chan->context, context, sizeof(bridge_channel->chan->context));
1692         bridge_channel->chan->priority = priority;
1693         bridge_channel->chan->pbx = pbx;
1694
1695         ast_channel_unlock(bridge_channel->chan);
1696
1697         return res;
1698 }
1699
1700 static int execute_menu_entry(struct conference_bridge *conference_bridge,
1701         struct conference_bridge_user *conference_bridge_user,
1702         struct ast_bridge_channel *bridge_channel,
1703         struct conf_menu_entry *menu_entry,
1704         struct conf_menu *menu)
1705 {
1706         struct conf_menu_action *menu_action;
1707         int isadmin = ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_ADMIN);
1708         int stop_prompts = 0;
1709         int res = 0;
1710
1711         AST_LIST_TRAVERSE(&menu_entry->actions, menu_action, action) {
1712                 switch (menu_action->id) {
1713                 case MENU_ACTION_TOGGLE_MUTE:
1714                         res |= action_toggle_mute(conference_bridge,
1715                                 conference_bridge_user,
1716                                 bridge_channel->chan);
1717                         break;
1718                 case MENU_ACTION_PLAYBACK:
1719                         if (!stop_prompts) {
1720                                 res |= action_playback(bridge_channel, menu_action->data.playback_file);
1721                         }
1722                         break;
1723                 case MENU_ACTION_RESET_LISTENING:
1724                         ast_audiohook_volume_set(conference_bridge_user->chan, AST_AUDIOHOOK_DIRECTION_WRITE, 0);
1725                         break;
1726                 case MENU_ACTION_RESET_TALKING:
1727                         ast_audiohook_volume_set(conference_bridge_user->chan, AST_AUDIOHOOK_DIRECTION_READ, 0);
1728                         break;
1729                 case MENU_ACTION_INCREASE_LISTENING:
1730                         ast_audiohook_volume_adjust(conference_bridge_user->chan,
1731                                 AST_AUDIOHOOK_DIRECTION_WRITE, 1);
1732                         break;
1733                 case MENU_ACTION_DECREASE_LISTENING:
1734                         ast_audiohook_volume_adjust(conference_bridge_user->chan,
1735                                 AST_AUDIOHOOK_DIRECTION_WRITE, -1);
1736                         break;
1737                 case MENU_ACTION_INCREASE_TALKING:
1738                         ast_audiohook_volume_adjust(conference_bridge_user->chan,
1739                                 AST_AUDIOHOOK_DIRECTION_READ, 1);
1740                         break;
1741                 case MENU_ACTION_DECREASE_TALKING:
1742                         ast_audiohook_volume_adjust(conference_bridge_user->chan,
1743                                 AST_AUDIOHOOK_DIRECTION_READ, -1);
1744                         break;
1745                 case MENU_ACTION_PLAYBACK_AND_CONTINUE:
1746                         if (!(stop_prompts)) {
1747                                 res |= action_playback_and_continue(conference_bridge,
1748                                         conference_bridge_user,
1749                                         bridge_channel,
1750                                         menu,
1751                                         menu_action->data.playback_file,
1752                                         menu_entry->dtmf,
1753                                         &stop_prompts);
1754                         }
1755                         break;
1756                 case MENU_ACTION_DIALPLAN_EXEC:
1757                         res |= action_dialplan_exec(bridge_channel, menu_action);
1758                         break;
1759                 case MENU_ACTION_ADMIN_TOGGLE_LOCK:
1760                         if (!isadmin) {
1761                                 break;
1762                         }
1763                         conference_bridge->locked = (!conference_bridge->locked ? 1 : 0);
1764                         res |= ast_stream_and_wait(bridge_channel->chan,
1765                                 (conference_bridge->locked ?
1766                                 conf_get_sound(CONF_SOUND_LOCKED_NOW, conference_bridge_user->b_profile.sounds) :
1767                                 conf_get_sound(CONF_SOUND_UNLOCKED_NOW, conference_bridge_user->b_profile.sounds)),
1768                                 "");
1769
1770                         break;
1771                 case MENU_ACTION_ADMIN_KICK_LAST:
1772                         res |= action_kick_last(conference_bridge, bridge_channel, conference_bridge_user);
1773                         break;
1774                 case MENU_ACTION_LEAVE:
1775                         ao2_lock(conference_bridge);
1776                         ast_bridge_remove(conference_bridge->bridge, bridge_channel->chan);
1777                         ao2_unlock(conference_bridge);
1778                         break;
1779                 case MENU_ACTION_NOOP:
1780                         break;
1781                 case MENU_ACTION_SET_SINGLE_VIDEO_SRC:
1782                         ao2_lock(conference_bridge);
1783                         ast_bridge_set_single_src_video_mode(conference_bridge->bridge, bridge_channel->chan);
1784                         ao2_unlock(conference_bridge);
1785                         break;
1786                 case MENU_ACTION_RELEASE_SINGLE_VIDEO_SRC:
1787                         handle_video_on_exit(conference_bridge, bridge_channel->chan);
1788                         break;
1789                 }
1790         }
1791         return res;
1792 }
1793
1794 int conf_handle_dtmf(struct ast_bridge_channel *bridge_channel,
1795         struct conference_bridge_user *conference_bridge_user,
1796         struct conf_menu_entry *menu_entry,
1797         struct conf_menu *menu)
1798 {
1799         struct conference_bridge *conference_bridge = conference_bridge_user->conference_bridge;
1800
1801         /* See if music on hold is playing */
1802         ao2_lock(conference_bridge);
1803         if (conference_bridge_user->playing_moh) {
1804                 /* MOH is going, let's stop it */
1805                 ast_moh_stop(bridge_channel->chan);
1806         }
1807         ao2_unlock(conference_bridge);
1808
1809         /* execute the list of actions associated with this menu entry */
1810         execute_menu_entry(conference_bridge, conference_bridge_user, bridge_channel, menu_entry, menu);
1811
1812         /* See if music on hold needs to be started back up again */
1813         ao2_lock(conference_bridge);
1814         if (conference_bridge_user->playing_moh) {
1815                 ast_moh_start(bridge_channel->chan, conference_bridge_user->u_profile.moh_class, NULL);
1816         }
1817         ao2_unlock(conference_bridge);
1818
1819         return 0;
1820 }
1821
1822 static char *complete_confbridge_name(const char *line, const char *word, int pos, int state)
1823 {
1824         int which = 0;
1825         struct conference_bridge *bridge = NULL;
1826         char *res = NULL;
1827         int wordlen = strlen(word);
1828         struct ao2_iterator i;
1829
1830         i = ao2_iterator_init(conference_bridges, 0);
1831         while ((bridge = ao2_iterator_next(&i))) {
1832                 if (!strncasecmp(bridge->name, word, wordlen) && ++which > state) {
1833                         res = ast_strdup(bridge->name);
1834                         ao2_ref(bridge, -1);
1835                         break;
1836                 }
1837                 ao2_ref(bridge, -1);
1838         }
1839         ao2_iterator_destroy(&i);
1840
1841         return res;
1842 }
1843
1844 static char *handle_cli_confbridge_kick(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1845 {
1846         struct conference_bridge *bridge = NULL;
1847         struct conference_bridge tmp;
1848         struct conference_bridge_user *participant = NULL;
1849
1850         switch (cmd) {
1851         case CLI_INIT:
1852                 e->command = "confbridge kick";
1853                 e->usage =
1854                         "Usage: confbridge kick <conference> <channel>\n"
1855                         "       Kicks a channel out of the conference bridge.\n";
1856                 return NULL;
1857         case CLI_GENERATE:
1858                 if (a->pos == 2) {
1859                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
1860                 }
1861                 /*
1862                 if (a->pos == 3) {
1863                         return complete_confbridge_channel(a->line, a->word, a->pos, a->n);
1864                 }
1865                 */
1866                 return NULL;
1867         }
1868
1869         if (a->argc != 4) {
1870                 return CLI_SHOWUSAGE;
1871         }
1872
1873         ast_copy_string(tmp.name, a->argv[2], sizeof(tmp.name));
1874         bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
1875         if (!bridge) {
1876                 ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
1877                 return CLI_SUCCESS;
1878         }
1879         ao2_lock(bridge);
1880         AST_LIST_TRAVERSE(&bridge->users_list, participant, list) {
1881                 if (!strncmp(a->argv[3], participant->chan->name, strlen(participant->chan->name))) {
1882                         break;
1883                 }
1884         }
1885         if (participant) {
1886                 ast_cli(a->fd, "Kicking %s from confbridge %s\n", participant->chan->name, bridge->name);
1887                 participant->kicked = 1;
1888                 ast_bridge_remove(bridge->bridge, participant->chan);
1889         }
1890         ao2_unlock(bridge);
1891         ao2_ref(bridge, -1);
1892         return CLI_SUCCESS;
1893 }
1894
1895 static char *handle_cli_confbridge_list(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1896 {
1897         struct ao2_iterator i;
1898         struct conference_bridge *bridge = NULL;
1899         struct conference_bridge tmp;
1900         struct conference_bridge_user *participant = NULL;
1901
1902         switch (cmd) {
1903         case CLI_INIT:
1904                 e->command = "confbridge list";
1905                 e->usage =
1906                         "Usage: confbridge list [<name>]\n"
1907                         "       Lists all currently active conference bridges.\n";
1908                 return NULL;
1909         case CLI_GENERATE:
1910                 if (a->pos == 2) {
1911                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
1912                 }
1913                 return NULL;
1914         }
1915
1916         if (a->argc == 2) {
1917                 ast_cli(a->fd, "Conference Bridge Name           Users  Marked Locked?\n");
1918                 ast_cli(a->fd, "================================ ====== ====== ========\n");
1919                 i = ao2_iterator_init(conference_bridges, 0);
1920                 while ((bridge = ao2_iterator_next(&i))) {
1921                         ast_cli(a->fd, "%-32s %6i %6i %s\n", bridge->name, bridge->users, bridge->markedusers, (bridge->locked ? "locked" : "unlocked"));
1922                         ao2_ref(bridge, -1);
1923                 }
1924                 ao2_iterator_destroy(&i);
1925                 return CLI_SUCCESS;
1926         }
1927
1928         if (a->argc == 3) {
1929                 ast_copy_string(tmp.name, a->argv[2], sizeof(tmp.name));
1930                 bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
1931                 if (!bridge) {
1932                         ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
1933                         return CLI_SUCCESS;
1934                 }
1935                 ast_cli(a->fd, "Channel                       User Profile     Bridge Profile   Menu\n");
1936                 ast_cli(a->fd, "============================= ================ ================ ================\n");
1937                 ao2_lock(bridge);
1938                 AST_LIST_TRAVERSE(&bridge->users_list, participant, list) {
1939                         ast_cli(a->fd, "%-29s ", participant->chan->name);
1940                         ast_cli(a->fd, "%-17s", participant->u_profile.name);
1941                         ast_cli(a->fd, "%-17s", participant->b_profile.name);
1942                         ast_cli(a->fd, "%-17s", participant->menu_name);
1943                         ast_cli(a->fd, "\n");
1944                 }
1945                 ao2_unlock(bridge);
1946                 ao2_ref(bridge, -1);
1947                 return CLI_SUCCESS;
1948         }
1949
1950         return CLI_SHOWUSAGE;
1951 }
1952
1953 /* \internal
1954  * \brief finds a conference by name and locks/unlocks.
1955  *
1956  * \retval 0 success
1957  * \retval -1 conference not found
1958  */
1959 static int generic_lock_unlock_helper(int lock, const char *conference)
1960 {
1961         struct conference_bridge *bridge = NULL;
1962         struct conference_bridge tmp;
1963         int res = 0;
1964
1965         ast_copy_string(tmp.name, conference, sizeof(tmp.name));
1966         bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
1967         if (!bridge) {
1968                 return -1;
1969         }
1970         ao2_lock(bridge);
1971         bridge->locked = lock;
1972         ao2_unlock(bridge);
1973         ao2_ref(bridge, -1);
1974
1975         return res;
1976 }
1977
1978 /* \internal
1979  * \brief finds a conference user by channel name and mutes/unmutes them.
1980  *
1981  * \retval 0 success
1982  * \retval -1 conference not found
1983  * \retval -2 user not found
1984  */
1985 static int generic_mute_unmute_helper(int mute, const char *conference, const char *user)
1986 {
1987         struct conference_bridge *bridge = NULL;
1988         struct conference_bridge tmp;
1989         struct conference_bridge_user *participant = NULL;
1990         int res = 0;
1991         ast_copy_string(tmp.name, conference, sizeof(tmp.name));
1992         bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
1993         if (!bridge) {
1994                 return -1;
1995         }
1996         ao2_lock(bridge);
1997         AST_LIST_TRAVERSE(&bridge->users_list, participant, list) {
1998                 if (!strncmp(user, participant->chan->name, strlen(user))) {
1999                         break;
2000                 }
2001         }
2002         if (participant) {
2003                 participant->features.mute = mute;
2004         } else {
2005                 res = -2;;
2006         }
2007         ao2_unlock(bridge);
2008         ao2_ref(bridge, -1);
2009
2010         return res;
2011 }
2012
2013 static int cli_mute_unmute_helper(int mute, struct ast_cli_args *a)
2014 {
2015         int res = generic_mute_unmute_helper(mute, a->argv[2], a->argv[3]);
2016
2017         if (res == -1) {
2018                 ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
2019                 return -1;
2020         } else if (res == -2) {
2021                 ast_cli(a->fd, "No channel named '%s' found in conference %s\n", a->argv[3], a->argv[2]);
2022                 return -1;
2023         }
2024         ast_cli(a->fd, "%s %s from confbridge %s\n", mute ? "Muting" : "Unmuting", a->argv[3], a->argv[2]);
2025         return 0;
2026 }
2027
2028 static char *handle_cli_confbridge_mute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2029 {
2030         switch (cmd) {
2031         case CLI_INIT:
2032                 e->command = "confbridge mute";
2033                 e->usage =
2034                         "Usage: confbridge mute <conference> <channel>\n";
2035                 return NULL;
2036         case CLI_GENERATE:
2037                 if (a->pos == 2) {
2038                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
2039                 }
2040                 return NULL;
2041         }
2042         if (a->argc != 4) {
2043                 return CLI_SHOWUSAGE;
2044         }
2045
2046         cli_mute_unmute_helper(1, a);
2047
2048         return CLI_SUCCESS;
2049 }
2050
2051 static char *handle_cli_confbridge_unmute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2052 {
2053         switch (cmd) {
2054         case CLI_INIT:
2055                 e->command = "confbridge unmute";
2056                 e->usage =
2057                         "Usage: confbridge unmute <conference> <channel>\n";
2058                 return NULL;
2059         case CLI_GENERATE:
2060                 if (a->pos == 2) {
2061                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
2062                 }
2063                 return NULL;
2064         }
2065         if (a->argc != 4) {
2066                 return CLI_SHOWUSAGE;
2067         }
2068
2069         cli_mute_unmute_helper(0, a);
2070
2071         return CLI_SUCCESS;
2072 }
2073
2074 static char *handle_cli_confbridge_lock(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2075 {
2076         switch (cmd) {
2077         case CLI_INIT:
2078                 e->command = "confbridge lock";
2079                 e->usage =
2080                         "Usage: confbridge lock <conference>\n";
2081                 return NULL;
2082         case CLI_GENERATE:
2083                 if (a->pos == 2) {
2084                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
2085                 }
2086                 return NULL;
2087         }
2088         if (a->argc != 3) {
2089                 return CLI_SHOWUSAGE;
2090         }
2091         if (generic_lock_unlock_helper(1, a->argv[2])) {
2092                 ast_cli(a->fd, "Conference %s is not found\n", a->argv[2]);
2093         } else {
2094                 ast_cli(a->fd, "Conference %s is locked.\n", a->argv[2]);
2095         }
2096         return CLI_SUCCESS;
2097 }
2098
2099 static char *handle_cli_confbridge_unlock(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2100 {
2101         switch (cmd) {
2102         case CLI_INIT:
2103                 e->command = "confbridge unlock";
2104                 e->usage =
2105                         "Usage: confbridge unlock <conference>\n";
2106                 return NULL;
2107         case CLI_GENERATE:
2108                 if (a->pos == 2) {
2109                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
2110                 }
2111                 return NULL;
2112         }
2113         if (a->argc != 3) {
2114                 return CLI_SHOWUSAGE;
2115         }
2116         if (generic_lock_unlock_helper(0, a->argv[2])) {
2117                 ast_cli(a->fd, "Conference %s is not found\n", a->argv[2]);
2118         } else {
2119                 ast_cli(a->fd, "Conference %s is unlocked.\n", a->argv[2]);
2120         }
2121         return CLI_SUCCESS;
2122 }
2123
2124 static char *handle_cli_confbridge_start_record(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2125 {
2126         const char *rec_file = NULL;
2127         struct conference_bridge *bridge = NULL;
2128         struct conference_bridge tmp;
2129
2130         switch (cmd) {
2131         case CLI_INIT:
2132                 e->command = "confbridge record start";
2133                 e->usage =
2134                         "Usage: confbridge record start <conference> <file>\n"
2135                         "       <file> is optional, Otherwise the bridge profile\n"
2136                         "       record file will be used.  If the bridge profile\n"
2137                         "       has no record file specified, a file will automatically\n"
2138                         "       be generated in the monitor directory\n";
2139                 return NULL;
2140         case CLI_GENERATE:
2141                 if (a->pos == 3) {
2142                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
2143                 }
2144                 return NULL;
2145         }
2146         if (a->argc < 4) {
2147                 return CLI_SHOWUSAGE;
2148         }
2149         if (a->argc == 5) {
2150                 rec_file = a->argv[4];
2151         }
2152
2153         ast_copy_string(tmp.name, a->argv[3], sizeof(tmp.name));
2154         bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
2155         if (!bridge) {
2156                 ast_cli(a->fd, "Conference not found.\n");
2157                 return CLI_FAILURE;
2158         }
2159         if (conf_is_recording(bridge)) {
2160                 ast_cli(a->fd, "Conference is already being recorded.\n");
2161                 ao2_ref(bridge, -1);
2162                 return CLI_SUCCESS;
2163         }
2164         if (!ast_strlen_zero(rec_file)) {
2165                 ao2_lock(bridge);
2166                 ast_copy_string(bridge->b_profile.rec_file, rec_file, sizeof(bridge->b_profile.rec_file));
2167                 ao2_unlock(bridge);
2168         }
2169         if (conf_start_record(bridge)) {
2170                 ast_cli(a->fd, "Could not start recording due to internal error.\n");
2171                 ao2_ref(bridge, -1);
2172                 return CLI_FAILURE;
2173         }
2174         ast_cli(a->fd, "Recording started\n");
2175         ao2_ref(bridge, -1);
2176         return CLI_SUCCESS;
2177 }
2178
2179 static char *handle_cli_confbridge_stop_record(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2180 {
2181         struct conference_bridge *bridge = NULL;
2182         struct conference_bridge tmp;
2183
2184         switch (cmd) {
2185         case CLI_INIT:
2186                 e->command = "confbridge record stop";
2187                 e->usage =
2188                         "Usage: confbridge record stop <conference>\n";
2189                 return NULL;
2190         case CLI_GENERATE:
2191                 if (a->pos == 3) {
2192                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
2193                 }
2194                 return NULL;
2195         }
2196         if (a->argc != 4) {
2197                 return CLI_SHOWUSAGE;
2198         }
2199
2200         ast_copy_string(tmp.name, a->argv[3], sizeof(tmp.name));
2201         bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
2202         if (!bridge) {
2203                 ast_cli(a->fd, "Conference not found.\n");
2204                 return CLI_SUCCESS;
2205         }
2206         conf_stop_record(bridge);
2207         ast_cli(a->fd, "Recording stopped.\n");
2208         ao2_ref(bridge, -1);
2209         return CLI_SUCCESS;
2210 }
2211
2212 static struct ast_cli_entry cli_confbridge[] = {
2213         AST_CLI_DEFINE(handle_cli_confbridge_list, "List conference bridges and participants."),
2214         AST_CLI_DEFINE(handle_cli_confbridge_kick, "Kick participants out of conference bridges."),
2215         AST_CLI_DEFINE(handle_cli_confbridge_mute, "Mute a participant."),
2216         AST_CLI_DEFINE(handle_cli_confbridge_unmute, "Mute a participant."),
2217         AST_CLI_DEFINE(handle_cli_confbridge_lock, "Lock a conference."),
2218         AST_CLI_DEFINE(handle_cli_confbridge_unlock, "Unlock a conference."),
2219         AST_CLI_DEFINE(handle_cli_confbridge_start_record, "Start recording a conference"),
2220         AST_CLI_DEFINE(handle_cli_confbridge_stop_record, "Stop recording a conference."),
2221 };
2222 static struct ast_custom_function confbridge_function = {
2223         .name = "CONFBRIDGE",
2224         .write = func_confbridge_helper,
2225 };
2226
2227 static int func_confbridge_info(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len);
2228 static struct ast_custom_function confbridge_info_function = {
2229         .name = "CONFBRIDGE_INFO",
2230         .read = func_confbridge_info,
2231 };
2232
2233 static int action_confbridgelist(struct mansession *s, const struct message *m)
2234 {
2235         const char *actionid = astman_get_header(m, "ActionID");
2236         const char *conference = astman_get_header(m, "Conference");
2237         struct conference_bridge_user *participant = NULL;
2238         struct conference_bridge *bridge = NULL;
2239         struct conference_bridge tmp;
2240         char id_text[80] = "";
2241         int total = 0;
2242
2243         if (!ast_strlen_zero(actionid)) {
2244                 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", actionid);
2245         }
2246         if (ast_strlen_zero(conference)) {
2247                 astman_send_error(s, m, "No Conference name provided.");
2248                 return 0;
2249         }
2250         if (!ao2_container_count(conference_bridges)) {
2251                 astman_send_error(s, m, "No active conferences.");
2252                 return 0;
2253         }
2254         ast_copy_string(tmp.name, conference, sizeof(tmp.name));
2255         bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
2256         if (!bridge) {
2257                 astman_send_error(s, m, "No Conference by that name found.");
2258                 return 0;
2259         }
2260
2261         astman_send_listack(s, m, "Confbridge user list will follow", "start");
2262
2263         ao2_lock(bridge);
2264         AST_LIST_TRAVERSE(&bridge->users_list, participant, list) {
2265                 total++;
2266                 astman_append(s,
2267                         "Event: ConfbridgeList\r\n"
2268                         "%s"
2269                         "Conference: %s\r\n"
2270                         "CallerIDNum: %s\r\n"
2271                         "CallerIDName: %s\r\n"
2272                         "Channel: %s\r\n"
2273                         "Admin: %s\r\n"
2274                         "MarkedUser: %s\r\n"
2275                         "\r\n",
2276                         id_text,
2277                         bridge->name,
2278                         S_COR(participant->chan->caller.id.number.valid, participant->chan->caller.id.number.str, "<unknown>"),
2279                         S_COR(participant->chan->caller.id.name.valid, participant->chan->caller.id.name.str, "<no name>"),
2280                         participant->chan->name,
2281                         ast_test_flag(&participant->u_profile, USER_OPT_ADMIN) ? "Yes" : "No",
2282                         ast_test_flag(&participant->u_profile, USER_OPT_MARKEDUSER) ? "Yes" : "No");
2283         }
2284         ao2_unlock(bridge);
2285         ao2_ref(bridge, -1);
2286
2287         astman_append(s,
2288         "Event: ConfbridgeListComplete\r\n"
2289         "EventList: Complete\r\n"
2290         "ListItems: %d\r\n"
2291         "%s"
2292         "\r\n", total, id_text);
2293
2294         return 0;
2295 }
2296
2297 static int action_confbridgelistrooms(struct mansession *s, const struct message *m)
2298 {
2299         const char *actionid = astman_get_header(m, "ActionID");
2300         struct conference_bridge *bridge = NULL;
2301         struct ao2_iterator i;
2302         char id_text[512] = "";
2303         int totalitems = 0;
2304
2305         if (!ast_strlen_zero(actionid)) {
2306                 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", actionid);
2307         }
2308
2309         if (!ao2_container_count(conference_bridges)) {
2310                 astman_send_error(s, m, "No active conferences.");
2311                 return 0;
2312         }
2313
2314         astman_send_listack(s, m, "Confbridge conferences will follow", "start");
2315
2316         /* Traverse the conference list */
2317         i = ao2_iterator_init(conference_bridges, 0);
2318         while ((bridge = ao2_iterator_next(&i))) {
2319                 totalitems++;
2320
2321                 ao2_lock(bridge);
2322                 astman_append(s,
2323                 "Event: ConfbridgeListRooms\r\n"
2324                 "%s"
2325                 "Conference: %s\r\n"
2326                 "Parties: %d\r\n"
2327                 "Marked: %d\r\n"
2328                 "Locked: %s\r\n"
2329                 "\r\n",
2330                 id_text,
2331                 bridge->name,
2332                 bridge->users,
2333                 bridge->markedusers,
2334                 bridge->locked ? "Yes" : "No"); 
2335                 ao2_unlock(bridge);
2336
2337                 ao2_ref(bridge, -1);
2338         }
2339         ao2_iterator_destroy(&i);
2340
2341         /* Send final confirmation */
2342         astman_append(s,
2343         "Event: ConfbridgeListRoomsComplete\r\n"
2344         "EventList: Complete\r\n"
2345         "ListItems: %d\r\n"
2346         "%s"
2347         "\r\n", totalitems, id_text);
2348         return 0;
2349 }
2350
2351 static int action_mute_unmute_helper(struct mansession *s, const struct message *m, int mute)
2352 {
2353         const char *conference = astman_get_header(m, "Conference");
2354         const char *channel = astman_get_header(m, "Channel");
2355         int res = 0;
2356
2357         if (ast_strlen_zero(conference)) {
2358                 astman_send_error(s, m, "No Conference name provided.");
2359                 return 0;
2360         }
2361         if (ast_strlen_zero(channel)) {
2362                 astman_send_error(s, m, "No channel name provided.");
2363                 return 0;
2364         }
2365         if (!ao2_container_count(conference_bridges)) {
2366                 astman_send_error(s, m, "No active conferences.");
2367                 return 0;
2368         }
2369
2370         res = generic_mute_unmute_helper(mute, conference, channel);
2371
2372         if (res == -1) {
2373                 astman_send_error(s, m, "No Conference by that name found.");
2374                 return 0;
2375         } else if (res == -2) {
2376                 astman_send_error(s, m, "No Channel by that name found in Conference.");
2377                 return 0;
2378         }
2379
2380         astman_send_ack(s, m, mute ? "User muted" : "User unmuted");
2381         return 0;
2382 }
2383
2384 static int action_confbridgeunmute(struct mansession *s, const struct message *m)
2385 {
2386         return action_mute_unmute_helper(s, m, 0);
2387 }
2388 static int action_confbridgemute(struct mansession *s, const struct message *m)
2389 {
2390         return action_mute_unmute_helper(s, m, 1);
2391 }
2392
2393 static int action_lock_unlock_helper(struct mansession *s, const struct message *m, int lock)
2394 {
2395         const char *conference = astman_get_header(m, "Conference");
2396         int res = 0;
2397
2398         if (ast_strlen_zero(conference)) {
2399                 astman_send_error(s, m, "No Conference name provided.");
2400                 return 0;
2401         }
2402         if (!ao2_container_count(conference_bridges)) {
2403                 astman_send_error(s, m, "No active conferences.");
2404                 return 0;
2405         }
2406         if ((res = generic_lock_unlock_helper(lock, conference))) {
2407                 astman_send_error(s, m, "No Conference by that name found.");
2408                 return 0;
2409         }
2410         astman_send_ack(s, m, lock ? "Conference locked" : "Conference unlocked");
2411         return 0;
2412 }
2413 static int action_confbridgeunlock(struct mansession *s, const struct message *m)
2414 {
2415         return action_lock_unlock_helper(s, m, 0);
2416 }
2417 static int action_confbridgelock(struct mansession *s, const struct message *m)
2418 {
2419         return action_lock_unlock_helper(s, m, 1);
2420 }
2421
2422 static int action_confbridgekick(struct mansession *s, const struct message *m)
2423 {
2424         const char *conference = astman_get_header(m, "Conference");
2425         const char *channel = astman_get_header(m, "Channel");
2426         struct conference_bridge_user *participant = NULL;
2427         struct conference_bridge *bridge = NULL;
2428         struct conference_bridge tmp;
2429         int found = 0;
2430
2431         if (ast_strlen_zero(conference)) {
2432                 astman_send_error(s, m, "No Conference name provided.");
2433                 return 0;
2434         }
2435         if (!ao2_container_count(conference_bridges)) {
2436                 astman_send_error(s, m, "No active conferences.");
2437                 return 0;
2438         }
2439         ast_copy_string(tmp.name, conference, sizeof(tmp.name));
2440         bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
2441         if (!bridge) {
2442                 astman_send_error(s, m, "No Conference by that name found.");
2443                 return 0;
2444         }
2445
2446         ao2_lock(bridge);
2447         AST_LIST_TRAVERSE(&bridge->users_list, participant, list) {
2448                 if (!strcasecmp(participant->chan->name, channel)) {
2449                         participant->kicked = 1;
2450                         ast_bridge_remove(bridge->bridge, participant->chan);
2451                         found = 1;
2452                         break;
2453                 }
2454         }
2455         ao2_unlock(bridge);
2456         ao2_ref(bridge, -1);
2457
2458         if (found) {
2459                 astman_send_ack(s, m, "User kicked");
2460         } else {
2461                 astman_send_error(s, m, "No Channel by that name found in Conference.");
2462         }
2463         return 0;
2464 }
2465
2466 static int action_confbridgestartrecord(struct mansession *s, const struct message *m)
2467 {
2468         const char *conference = astman_get_header(m, "Conference");
2469         const char *recordfile = astman_get_header(m, "RecordFile");
2470         struct conference_bridge *bridge = NULL;
2471         struct conference_bridge tmp;
2472
2473         if (ast_strlen_zero(conference)) {
2474                 astman_send_error(s, m, "No Conference name provided.");
2475                 return 0;
2476         }
2477         if (!ao2_container_count(conference_bridges)) {
2478                 astman_send_error(s, m, "No active conferences.");
2479                 return 0;
2480         }
2481
2482         ast_copy_string(tmp.name, conference, sizeof(tmp.name));
2483         bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
2484         if (!bridge) {
2485                 astman_send_error(s, m, "No Conference by that name found.");
2486                 return 0;
2487         }
2488
2489         if (conf_is_recording(bridge)) {
2490                 astman_send_error(s, m, "Conference is already being recorded.");
2491                 ao2_ref(bridge, -1);
2492                 return 0;
2493         }
2494
2495         if (!ast_strlen_zero(recordfile)) {
2496                 ao2_lock(bridge);
2497                 ast_copy_string(bridge->b_profile.rec_file, recordfile, sizeof(bridge->b_profile.rec_file));
2498                 ao2_unlock(bridge);
2499         }
2500
2501         if (conf_start_record(bridge)) {
2502                 astman_send_error(s, m, "Internal error starting conference recording.");
2503                 ao2_ref(bridge, -1);
2504                 return 0;
2505         }
2506
2507         ao2_ref(bridge, -1);
2508         astman_send_ack(s, m, "Conference Recording Started.");
2509         return 0;
2510 }
2511 static int action_confbridgestoprecord(struct mansession *s, const struct message *m)
2512 {
2513         const char *conference = astman_get_header(m, "Conference");
2514         struct conference_bridge *bridge = NULL;
2515         struct conference_bridge tmp;
2516
2517         if (ast_strlen_zero(conference)) {
2518                 astman_send_error(s, m, "No Conference name provided.");
2519                 return 0;
2520         }
2521         if (!ao2_container_count(conference_bridges)) {
2522                 astman_send_error(s, m, "No active conferences.");
2523                 return 0;
2524         }
2525
2526         ast_copy_string(tmp.name, conference, sizeof(tmp.name));
2527         bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
2528         if (!bridge) {
2529                 astman_send_error(s, m, "No Conference by that name found.");
2530                 return 0;
2531         }
2532
2533         if (conf_stop_record(bridge)) {
2534                 astman_send_error(s, m, "Internal error while stopping recording.");
2535                 ao2_ref(bridge, -1);
2536                 return 0;
2537         }
2538
2539         ao2_ref(bridge, -1);
2540         astman_send_ack(s, m, "Conference Recording Stopped.");
2541         return 0;
2542 }
2543
2544 static int action_confbridgesetsinglevideosrc(struct mansession *s, const struct message *m)
2545 {
2546         const char *conference = astman_get_header(m, "Conference");
2547         const char *channel = astman_get_header(m, "Channel");
2548         struct conference_bridge_user *participant = NULL;
2549         struct conference_bridge *bridge = NULL;
2550         struct conference_bridge tmp;
2551
2552         if (ast_strlen_zero(conference)) {
2553                 astman_send_error(s, m, "No Conference name provided.");
2554                 return 0;
2555         }
2556         if (ast_strlen_zero(channel)) {
2557                 astman_send_error(s, m, "No channel name provided.");
2558                 return 0;
2559         }
2560         if (!ao2_container_count(conference_bridges)) {
2561                 astman_send_error(s, m, "No active conferences.");
2562                 return 0;
2563         }
2564
2565         ast_copy_string(tmp.name, conference, sizeof(tmp.name));
2566         bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
2567         if (!bridge) {
2568                 astman_send_error(s, m, "No Conference by that name found.");
2569                 return 0;
2570         }
2571
2572         /* find channel and set as video src. */
2573         ao2_lock(bridge);
2574         AST_LIST_TRAVERSE(&bridge->users_list, participant, list) {
2575                 if (!strncmp(channel, participant->chan->name, strlen(channel))) {
2576                         ast_bridge_set_single_src_video_mode(bridge->bridge, participant->chan);
2577                         break;
2578                 }
2579         }
2580         ao2_unlock(bridge);
2581         ao2_ref(bridge, -1);
2582
2583         /* do not access participant after bridge unlock.  We are just
2584          * using this check to see if it was found or not */
2585         if (!participant) {
2586                 astman_send_error(s, m, "No channel by that name found in conference.");
2587                 return 0;
2588         }
2589         astman_send_ack(s, m, "Conference single video source set.");
2590         return 0;
2591 }
2592
2593 static int func_confbridge_info(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
2594 {
2595         char *parse = NULL;
2596         struct conference_bridge *bridge = NULL;
2597         struct conference_bridge_user *participant = NULL;
2598         struct conference_bridge tmp;
2599         int count = 0;
2600         AST_DECLARE_APP_ARGS(args,
2601                 AST_APP_ARG(type);
2602                 AST_APP_ARG(confno);
2603         );
2604
2605         /* parse all the required arguments and make sure they exist. */
2606         if (ast_strlen_zero(data)) {
2607                 return -1;
2608         }
2609         parse = ast_strdupa(data);
2610         AST_STANDARD_APP_ARGS(args, parse);
2611         if (ast_strlen_zero(args.confno) || ast_strlen_zero(args.type)) {
2612                 return -1;
2613         }
2614         if (!ao2_container_count(conference_bridges)) {
2615                 ast_log(LOG_ERROR, "No active conferneces.\n");
2616                 return -1;
2617         }
2618         ast_copy_string(tmp.name, args.confno, sizeof(tmp.name));
2619         bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
2620         if (!bridge) {
2621                 ast_log(LOG_ERROR, "Confernece '%s' not found.\n", args.confno);
2622                 return -1;
2623         }
2624
2625         /* get the correct count for the type requested */
2626         ao2_lock(bridge);
2627         if (!strncasecmp(args.type, "parties", 7)) {
2628                 AST_LIST_TRAVERSE(&bridge->users_list, participant, list) {
2629                         count++;
2630                 }
2631         } else if (!strncasecmp(args.type, "admins", 6)) {
2632                 AST_LIST_TRAVERSE(&bridge->users_list, participant, list) {
2633                         if (ast_test_flag(&participant->u_profile, USER_OPT_ADMIN)) {
2634                                 count++;
2635                         }
2636                 }
2637         } else if (!strncasecmp(args.type, "marked", 6)) {
2638                 AST_LIST_TRAVERSE(&bridge->users_list, participant, list) {
2639                         if (ast_test_flag(&participant->u_profile, USER_OPT_MARKEDUSER)) {
2640                                 count++;
2641                         }
2642                 }
2643         } else if (!strncasecmp(args.type, "locked", 6)) {
2644                 count = bridge->locked;
2645         } else {
2646                 ao2_unlock(bridge);
2647                 ao2_ref(bridge, -1);
2648                 return -1;
2649         }
2650         snprintf(buf, len, "%d", count);
2651         ao2_unlock(bridge);
2652         ao2_ref(bridge, -1);
2653         return 0;
2654 }
2655
2656 /*! \brief Called when module is being unloaded */
2657 static int unload_module(void)
2658 {
2659         int res = ast_unregister_application(app);
2660
2661         ast_custom_function_unregister(&confbridge_function);
2662         ast_custom_function_unregister(&confbridge_info_function);
2663
2664         ast_cli_unregister_multiple(cli_confbridge, sizeof(cli_confbridge) / sizeof(struct ast_cli_entry));
2665
2666         /* Get rid of the conference bridges container. Since we only allow dynamic ones none will be active. */
2667         ao2_ref(conference_bridges, -1);
2668
2669         conf_destroy_config();
2670
2671         ast_channel_unregister(&record_tech);
2672         record_tech.capabilities = ast_format_cap_destroy(record_tech.capabilities);
2673
2674         res |= ast_manager_unregister("ConfbridgeList");
2675         res |= ast_manager_unregister("ConfbridgeListRooms");
2676         res |= ast_manager_unregister("ConfbridgeMute");
2677         res |= ast_manager_unregister("ConfbridgeUnmute");
2678         res |= ast_manager_unregister("ConfbridgeKick");
2679         res |= ast_manager_unregister("ConfbridgeUnlock");
2680         res |= ast_manager_unregister("ConfbridgeLock");
2681         res |= ast_manager_unregister("ConfbridgeStartRecord");
2682         res |= ast_manager_unregister("ConfbridgeStopRecord");
2683
2684         return res;
2685 }
2686
2687 /*! \brief Called when module is being loaded */
2688 static int load_module(void)
2689 {
2690         int res = 0;
2691         if ((ast_custom_function_register(&confbridge_function))) {
2692                 return AST_MODULE_LOAD_FAILURE;
2693         }
2694         if ((ast_custom_function_register(&confbridge_info_function))) {
2695                 return AST_MODULE_LOAD_FAILURE;
2696         }
2697         if (!(record_tech.capabilities = ast_format_cap_alloc())) {
2698                 return AST_MODULE_LOAD_FAILURE;
2699         }
2700         ast_format_cap_add_all(record_tech.capabilities);
2701         if (ast_channel_register(&record_tech)) {
2702                 ast_log(LOG_ERROR, "Unable to register ConfBridge recorder.\n");
2703                 return AST_MODULE_LOAD_FAILURE;
2704         }
2705         /* Create a container to hold the conference bridges */
2706         if (!(conference_bridges = ao2_container_alloc(CONFERENCE_BRIDGE_BUCKETS, conference_bridge_hash_cb, conference_bridge_cmp_cb))) {
2707                 return AST_MODULE_LOAD_FAILURE;
2708         }
2709         if (ast_register_application_xml(app, confbridge_exec)) {
2710                 ao2_ref(conference_bridges, -1);
2711                 return AST_MODULE_LOAD_FAILURE;
2712         }
2713
2714         res |= ast_cli_register_multiple(cli_confbridge, sizeof(cli_confbridge) / sizeof(struct ast_cli_entry));
2715         res |= ast_manager_register_xml("ConfbridgeList", EVENT_FLAG_REPORTING, action_confbridgelist);
2716         res |= ast_manager_register_xml("ConfbridgeListRooms", EVENT_FLAG_REPORTING, action_confbridgelistrooms);
2717         res |= ast_manager_register_xml("ConfbridgeMute", EVENT_FLAG_CALL, action_confbridgemute);
2718         res |= ast_manager_register_xml("ConfbridgeUnmute", EVENT_FLAG_CALL, action_confbridgeunmute);
2719         res |= ast_manager_register_xml("ConfbridgeKick", EVENT_FLAG_CALL, action_confbridgekick);
2720         res |= ast_manager_register_xml("ConfbridgeUnlock", EVENT_FLAG_CALL, action_confbridgeunlock);
2721         res |= ast_manager_register_xml("ConfbridgeLock", EVENT_FLAG_CALL, action_confbridgelock);
2722         res |= ast_manager_register_xml("ConfbridgeStartRecord", EVENT_FLAG_CALL, action_confbridgestartrecord);
2723         res |= ast_manager_register_xml("ConfbridgeStopRecord", EVENT_FLAG_CALL, action_confbridgestoprecord);
2724         res |= ast_manager_register_xml("ConfbridgeSetSingleVideoSrc", EVENT_FLAG_CALL, action_confbridgesetsinglevideosrc);
2725
2726         conf_load_config(0);
2727         return res;
2728 }
2729
2730 static int reload(void)
2731 {
2732         return conf_load_config(1);
2733 }
2734
2735 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Conference Bridge Application",
2736         .load = load_module,
2737         .unload = unload_module,
2738         .reload = reload,
2739         .load_pri = AST_MODPRI_DEVSTATE_PROVIDER,
2740 );