d046c489f3678398397c260cef0b1e78c3a5245e
[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 conference_bridge_user *conference_bridge_user)
636 {
637         /* only automatically set video source for marked users */
638         if (!ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MARKEDUSER)) {
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 == conference_bridge_user) {
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, conference_bridge_user->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, conference_bridge_user->chan);
663         }
664 }
665
666 static void handle_video_on_exit(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user)
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, conference_bridge_user->chan)) {
672                 return;
673         }
674
675         ast_bridge_remove_video_src(conference_bridge->bridge, conference_bridge_user->chan);
676
677         /* if the video_mode isn't set to automatically pick the video source, do nothing on exit. */
678         if (!ast_test_flag(&conference_bridge->b_profile, BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED) &&
679                 !ast_test_flag(&conference_bridge->b_profile, BRIDGE_OPT_VIDEO_SRC_LAST_MARKED)) {
680                 return;
681         }
682
683         /* Make the next avaliable marked user the video src.  */
684         ao2_lock(conference_bridge);
685         AST_LIST_TRAVERSE(&conference_bridge->users_list, tmp_user, list) {
686                 if (tmp_user == conference_bridge_user) {
687                         continue;
688                 }
689                 if (ast_test_flag(&tmp_user->u_profile, USER_OPT_MARKEDUSER)) {
690                         ast_bridge_set_single_src_video_mode(conference_bridge->bridge, tmp_user->chan);
691                         break;
692                 }
693         }
694         ao2_unlock(conference_bridge);
695 }
696
697 /*!
698  * \brief Perform post-joining marked specific actions
699  *
700  * \param conference_bridge Conference bridge being joined
701  * \param conference_bridge_user Conference bridge user joining
702  *
703  * \return Returns 0 on success, -1 if the user hung up
704  */
705 static int post_join_marked(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user)
706 {
707         if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MARKEDUSER)) {
708                 struct conference_bridge_user *other_conference_bridge_user = NULL;
709
710                 /* If we are not the first user to join, then the users are already
711                  * in the conference so we do not need to update them. */
712                 if (conference_bridge->markedusers >= 2) {
713                         return 0;
714                 }
715
716                 /* Iterate through every participant stopping MOH on them if need be */
717                 AST_LIST_TRAVERSE(&conference_bridge->users_list, other_conference_bridge_user, list) {
718                         if (other_conference_bridge_user == conference_bridge_user) {
719                                 continue;
720                         }
721                         if (other_conference_bridge_user->playing_moh && !ast_bridge_suspend(conference_bridge->bridge, other_conference_bridge_user->chan)) {
722                                 other_conference_bridge_user->playing_moh = 0;
723                                 ast_moh_stop(other_conference_bridge_user->chan);
724                                 ast_bridge_unsuspend(conference_bridge->bridge, other_conference_bridge_user->chan);
725                         }
726                 }
727
728                 /* Next play the audio file stating they are going to be placed into the conference */
729                 if (!ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_QUIET)) {
730                         ao2_unlock(conference_bridge);
731                         ast_autoservice_start(conference_bridge_user->chan);
732                         play_sound_file(conference_bridge,
733                                 conf_get_sound(CONF_SOUND_PLACE_IN_CONF, conference_bridge_user->b_profile.sounds));
734                         ast_autoservice_stop(conference_bridge_user->chan);
735                         ao2_lock(conference_bridge);
736                 }
737
738                 /* Finally iterate through and unmute them all */
739                 AST_LIST_TRAVERSE(&conference_bridge->users_list, other_conference_bridge_user, list) {
740                         if (other_conference_bridge_user == conference_bridge_user) {
741                                 continue;
742                         }
743                         /* only unmute them if they are not supposed to start muted */
744                         if (!ast_test_flag(&other_conference_bridge_user->u_profile, USER_OPT_STARTMUTED)) {
745                                 other_conference_bridge_user->features.mute = 0;
746                         }
747                 }
748         } else {
749                 /* If a marked user already exists in the conference bridge we can just bail out now */
750                 if (conference_bridge->markedusers) {
751                         return 0;
752                 }
753                 /* Be sure we are muted so we can't talk to anybody else waiting */
754                 conference_bridge_user->features.mute = 1;
755                 /* If we have not been quieted play back that they are waiting for the leader */
756                 if (!ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_QUIET)) {
757                         if (play_prompt_to_channel(conference_bridge,
758                                 conference_bridge_user->chan,
759                                 conf_get_sound(CONF_SOUND_WAIT_FOR_LEADER, conference_bridge_user->b_profile.sounds))) {
760                                 /* user hungup while the sound was playing */
761                                 return -1;
762                         }
763                 }
764                 /* Start music on hold if needed */
765                 /* We need to recheck the markedusers value here. play_prompt_to_channel unlocks the conference bridge, potentially
766                  * allowing a marked user to enter while the prompt was playing
767                  */
768                 if (!conference_bridge->markedusers && ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MUSICONHOLD)) {
769                         ast_moh_start(conference_bridge_user->chan, conference_bridge_user->u_profile.moh_class, NULL);
770                         conference_bridge_user->playing_moh = 1;
771                 }
772         }
773         return 0;
774 }
775
776 /*!
777  * \brief Perform post-joining non-marked specific actions
778  *
779  * \param conference_bridge Conference bridge being joined
780  * \param conference_bridge_user Conference bridge user joining
781  *
782  * \return Returns 0 on success, -1 if the user hung up
783  */
784 static int post_join_unmarked(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user)
785 {
786         /* Play back audio prompt and start MOH if need be if we are the first participant */
787         if (conference_bridge->users == 1) {
788                 /* If audio prompts have not been quieted or this prompt quieted play it on out */
789                 if (!ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_QUIET | USER_OPT_NOONLYPERSON)) {
790                         if (play_prompt_to_channel(conference_bridge,
791                                 conference_bridge_user->chan,
792                                 conf_get_sound(CONF_SOUND_ONLY_PERSON, conference_bridge_user->b_profile.sounds))) {
793                                 /* user hungup while the sound was playing */
794                                 return -1;
795                         }
796                 }
797                 /* If we need to start music on hold on the channel do so now */
798                 /* We need to re-check the number of users in the conference bridge here because another conference bridge
799                  * participant could have joined while the above prompt was playing for the first user.
800                  */
801                 if (conference_bridge->users == 1 && ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MUSICONHOLD)) {
802                         ast_moh_start(conference_bridge_user->chan, conference_bridge_user->u_profile.moh_class, NULL);
803                         conference_bridge_user->playing_moh = 1;
804                 }
805                 return 0;
806         }
807
808         /* Announce number of users if need be */
809         if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_ANNOUNCEUSERCOUNT)) {
810                 ao2_unlock(conference_bridge);
811                 if (announce_user_count(conference_bridge, conference_bridge_user)) {
812                         ao2_lock(conference_bridge);
813                         return -1;
814                 }
815                 ao2_lock(conference_bridge);
816         }
817
818         /* If we are the second participant we may need to stop music on hold on the first */
819         if (conference_bridge->users == 2) {
820                 struct conference_bridge_user *first_participant = AST_LIST_FIRST(&conference_bridge->users_list);
821
822                 /* Temporarily suspend the above participant from the bridge so we have control to stop MOH if needed */
823                 if (ast_test_flag(&first_participant->u_profile, USER_OPT_MUSICONHOLD) && !ast_bridge_suspend(conference_bridge->bridge, first_participant->chan)) {
824                         first_participant->playing_moh = 0;
825                         ast_moh_stop(first_participant->chan);
826                         ast_bridge_unsuspend(conference_bridge->bridge, first_participant->chan);
827                 }
828         }
829
830         if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_ANNOUNCEUSERCOUNTALL) &&
831                 (conference_bridge->users > conference_bridge_user->u_profile.announce_user_count_all_after)) {
832                 ao2_unlock(conference_bridge);
833                 if (announce_user_count(conference_bridge, NULL)) {
834                         ao2_lock(conference_bridge);
835                         return -1;
836                 }
837                 ao2_lock(conference_bridge);
838         }
839         return 0;
840 }
841
842 /*!
843  * \brief Destroy a conference bridge
844  *
845  * \param obj The conference bridge object
846  *
847  * \return Returns nothing
848  */
849 static void destroy_conference_bridge(void *obj)
850 {
851         struct conference_bridge *conference_bridge = obj;
852
853         ast_debug(1, "Destroying conference bridge '%s'\n", conference_bridge->name);
854
855         ast_mutex_destroy(&conference_bridge->playback_lock);
856
857         if (conference_bridge->playback_chan) {
858                 struct ast_channel *underlying_channel = conference_bridge->playback_chan->tech->bridged_channel(conference_bridge->playback_chan, NULL);
859                 ast_hangup(underlying_channel);
860                 ast_hangup(conference_bridge->playback_chan);
861                 conference_bridge->playback_chan = NULL;
862         }
863
864         /* Destroying a conference bridge is simple, all we have to do is destroy the bridging object */
865         if (conference_bridge->bridge) {
866                 ast_bridge_destroy(conference_bridge->bridge);
867                 conference_bridge->bridge = NULL;
868         }
869         conf_bridge_profile_destroy(&conference_bridge->b_profile);
870 }
871
872 static void leave_conference_bridge(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user);
873
874 /*!
875  * \brief Join a conference bridge
876  *
877  * \param name The conference name
878  * \param conference_bridge_user Conference bridge user structure
879  *
880  * \return A pointer to the conference bridge struct, or NULL if the conference room wasn't found.
881  */
882 static struct conference_bridge *join_conference_bridge(const char *name, struct conference_bridge_user *conference_bridge_user)
883 {
884         struct conference_bridge *conference_bridge = NULL;
885         struct conference_bridge tmp;
886         int start_record = 0;
887         int max_members_reached = 0;
888
889         ast_copy_string(tmp.name, name, sizeof(tmp.name));
890
891         /* We explictly lock the conference bridges container ourselves so that other callers can not create duplicate conferences at the same */
892         ao2_lock(conference_bridges);
893
894         ast_debug(1, "Trying to find conference bridge '%s'\n", name);
895
896         /* Attempt to find an existing conference bridge */
897         conference_bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
898
899         if (conference_bridge && conference_bridge->b_profile.max_members) {
900                 max_members_reached = conference_bridge->b_profile.max_members > conference_bridge->users ? 0 : 1;
901         }
902
903         /* When finding a conference bridge that already exists make sure that it is not locked, and if so that we are not an admin */
904         if (conference_bridge && (max_members_reached || conference_bridge->locked) && !ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_ADMIN)) {
905                 ao2_unlock(conference_bridges);
906                 ao2_ref(conference_bridge, -1);
907                 ast_debug(1, "Conference bridge '%s' is locked and caller is not an admin\n", name);
908                 ast_stream_and_wait(conference_bridge_user->chan,
909                                 conf_get_sound(CONF_SOUND_LOCKED, conference_bridge_user->b_profile.sounds),
910                                 "");
911                 return NULL;
912         }
913
914         /* If no conference bridge was found see if we can create one */
915         if (!conference_bridge) {
916                 /* Try to allocate memory for a new conference bridge, if we fail... this won't end well. */
917                 if (!(conference_bridge = ao2_alloc(sizeof(*conference_bridge), destroy_conference_bridge))) {
918                         ao2_unlock(conference_bridges);
919                         ast_log(LOG_ERROR, "Conference bridge '%s' does not exist.\n", name);
920                         return NULL;
921                 }
922
923                 /* Setup conference bridge parameters */
924                 conference_bridge->record_thread = AST_PTHREADT_NULL;
925                 ast_copy_string(conference_bridge->name, name, sizeof(conference_bridge->name));
926                 conf_bridge_profile_copy(&conference_bridge->b_profile, &conference_bridge_user->b_profile);
927
928                 /* Create an actual bridge that will do the audio mixing */
929                 if (!(conference_bridge->bridge = ast_bridge_new(AST_BRIDGE_CAPABILITY_MULTIMIX, 0))) {
930                         ao2_ref(conference_bridge, -1);
931                         conference_bridge = NULL;
932                         ao2_unlock(conference_bridges);
933                         ast_log(LOG_ERROR, "Conference bridge '%s' could not be created.\n", name);
934                         return NULL;
935                 }
936
937                 /* Set the internal sample rate on the bridge from the bridge profile */
938                 ast_bridge_set_internal_sample_rate(conference_bridge->bridge, conference_bridge->b_profile.internal_sample_rate);
939                 /* Set the internal mixing interval on the bridge from the bridge profile */
940                 ast_bridge_set_mixing_interval(conference_bridge->bridge, conference_bridge->b_profile.mix_interval);
941
942                 if (ast_test_flag(&conference_bridge->b_profile, BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER)) {
943                         ast_bridge_set_talker_src_video_mode(conference_bridge->bridge);
944                 }
945
946                 /* Setup lock for playback channel */
947                 ast_mutex_init(&conference_bridge->playback_lock);
948
949                 /* Link it into the conference bridges container */
950                 ao2_link(conference_bridges, conference_bridge);
951
952
953                 send_conf_start_event(conference_bridge->name);
954                 ast_debug(1, "Created conference bridge '%s' and linked to container '%p'\n", name, conference_bridges);
955         }
956
957         ao2_unlock(conference_bridges);
958
959         /* Setup conference bridge user parameters */
960         conference_bridge_user->conference_bridge = conference_bridge;
961
962         ao2_lock(conference_bridge);
963
964         /* All good to go, add them in */
965         AST_LIST_INSERT_TAIL(&conference_bridge->users_list, conference_bridge_user, list);
966
967         /* Increment the users count on the bridge, but record it as it is going to need to be known right after this */
968         conference_bridge->users++;
969
970         /* If the caller is a marked user bump up the count */
971         if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MARKEDUSER)) {
972                 conference_bridge->markedusers++;
973         }
974
975         /* Set the device state for this conference */
976         if (conference_bridge->users == 1) {
977                 ast_devstate_changed(AST_DEVICE_INUSE, "confbridge:%s", conference_bridge->name);
978         }
979
980         /* 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 */
981         if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MARKEDUSER | USER_OPT_WAITMARKED)) {
982                 if (post_join_marked(conference_bridge, conference_bridge_user)) {
983                         ao2_unlock(conference_bridge);
984                         leave_conference_bridge(conference_bridge, conference_bridge_user);
985                         return NULL;
986                 }
987         } else {
988                 if (post_join_unmarked(conference_bridge, conference_bridge_user)) {
989                         ao2_unlock(conference_bridge);
990                         leave_conference_bridge(conference_bridge, conference_bridge_user);
991                         return NULL;
992                 }
993         }
994
995         /* check to see if recording needs to be started or not */
996         if (ast_test_flag(&conference_bridge->b_profile, BRIDGE_OPT_RECORD_CONFERENCE) && !conf_is_recording(conference_bridge)) {
997                 start_record = 1;
998         }
999
1000         ao2_unlock(conference_bridge);
1001
1002         if (start_record) {
1003                 conf_start_record(conference_bridge);
1004         }
1005
1006         return conference_bridge;
1007 }
1008
1009 /*!
1010  * \brief Leave a conference bridge
1011  *
1012  * \param conference_bridge The conference bridge to leave
1013  * \param conference_bridge_user The conference bridge user structure
1014  *
1015  */
1016 static void leave_conference_bridge(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user)
1017 {
1018         ao2_lock(conference_bridge);
1019
1020         /* If this caller is a marked user bump down the count */
1021         if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MARKEDUSER)) {
1022                 conference_bridge->markedusers--;
1023         }
1024
1025         /* Decrement the users count while keeping the previous participant count */
1026         conference_bridge->users--;
1027
1028         /* Drop conference bridge user from the list, they be going bye bye */
1029         AST_LIST_REMOVE(&conference_bridge->users_list, conference_bridge_user, list);
1030
1031         /* If there are still users in the conference bridge we may need to do things (such as start MOH on them) */
1032         if (conference_bridge->users) {
1033                 if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MARKEDUSER) && !conference_bridge->markedusers) {
1034                         struct conference_bridge_user *other_participant = NULL;
1035
1036                         /* Start out with muting everyone */
1037                         AST_LIST_TRAVERSE(&conference_bridge->users_list, other_participant, list) {
1038                                 other_participant->features.mute = 1;
1039                         }
1040
1041                         /* Play back the audio prompt saying the leader has left the conference */
1042                         if (!ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_QUIET)) {
1043                                 ao2_unlock(conference_bridge);
1044                                 ast_autoservice_start(conference_bridge_user->chan);
1045                                 play_sound_file(conference_bridge,
1046                                         conf_get_sound(CONF_SOUND_LEADER_HAS_LEFT, conference_bridge_user->b_profile.sounds));
1047                                 ast_autoservice_stop(conference_bridge_user->chan);
1048                                 ao2_lock(conference_bridge);
1049                         }
1050
1051                         /* Now on to starting MOH or kick if needed */
1052                         AST_LIST_TRAVERSE(&conference_bridge->users_list, other_participant, list) {
1053                                 if (ast_test_flag(&other_participant->u_profile, USER_OPT_ENDMARKED)) {
1054                                         other_participant->kicked = 1;
1055                                         ast_bridge_remove(conference_bridge->bridge, other_participant->chan);
1056                                 } else if (ast_test_flag(&other_participant->u_profile, USER_OPT_MUSICONHOLD) && !ast_bridge_suspend(conference_bridge->bridge, other_participant->chan)) {
1057                                         ast_moh_start(other_participant->chan, other_participant->u_profile.moh_class, NULL);
1058                                         other_participant->playing_moh = 1;
1059                                         ast_bridge_unsuspend(conference_bridge->bridge, other_participant->chan);
1060                                 }
1061                         }
1062                 } else if (conference_bridge->users == 1) {
1063                         /* Of course if there is one other person in here we may need to start up MOH on them */
1064                         struct conference_bridge_user *first_participant = AST_LIST_FIRST(&conference_bridge->users_list);
1065
1066                         if (ast_test_flag(&first_participant->u_profile, USER_OPT_MUSICONHOLD) && !ast_bridge_suspend(conference_bridge->bridge, first_participant->chan)) {
1067                                 ast_moh_start(first_participant->chan, first_participant->u_profile.moh_class, NULL);
1068                                 first_participant->playing_moh = 1;
1069                                 ast_bridge_unsuspend(conference_bridge->bridge, first_participant->chan);
1070                         }
1071                 }
1072         } else {
1073                 /* Set device state to "not in use" */
1074                 ast_devstate_changed(AST_DEVICE_NOT_INUSE, "confbridge:%s", conference_bridge->name);
1075
1076                 ao2_unlink(conference_bridges, conference_bridge);
1077                 send_conf_end_event(conference_bridge->name);
1078         }
1079
1080         /* Done mucking with the conference bridge, huzzah */
1081         ao2_unlock(conference_bridge);
1082
1083         if (!conference_bridge->users) {
1084                 conf_stop_record(conference_bridge);
1085         }
1086
1087         ao2_ref(conference_bridge, -1);
1088 }
1089
1090 /*!
1091  * \internal
1092  * \brief allocates playback chan on a channel
1093  * \pre expects conference to be locked before calling this function
1094  */
1095 static int alloc_playback_chan(struct conference_bridge *conference_bridge)
1096 {
1097         int cause;
1098         struct ast_format_cap *cap;
1099         struct ast_format tmpfmt;
1100
1101         if (conference_bridge->playback_chan) {
1102                 return 0;
1103         }
1104         if (!(cap = ast_format_cap_alloc_nolock())) {
1105                 return -1;
1106         }
1107         ast_format_cap_add(cap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
1108         if (!(conference_bridge->playback_chan = ast_request("Bridge", cap, NULL, "", &cause))) {
1109                 cap = ast_format_cap_destroy(cap);
1110                 return -1;
1111         }
1112         cap = ast_format_cap_destroy(cap);
1113
1114         conference_bridge->playback_chan->bridge = conference_bridge->bridge;
1115
1116         if (ast_call(conference_bridge->playback_chan, "", 0)) {
1117                 ast_hangup(conference_bridge->playback_chan);
1118                 conference_bridge->playback_chan = NULL;
1119                 return -1;
1120         }
1121
1122         ast_debug(1, "Created a playback channel to conference bridge '%s'\n", conference_bridge->name);
1123         return 0;
1124 }
1125
1126 static int play_sound_helper(struct conference_bridge *conference_bridge, const char *filename, int say_number)
1127 {
1128         struct ast_channel *underlying_channel;
1129
1130         ast_mutex_lock(&conference_bridge->playback_lock);
1131         if (!(conference_bridge->playback_chan)) {
1132                 if (alloc_playback_chan(conference_bridge)) {
1133                         ast_mutex_unlock(&conference_bridge->playback_lock);
1134                         return -1;
1135                 }
1136                 underlying_channel = conference_bridge->playback_chan->tech->bridged_channel(conference_bridge->playback_chan, NULL);
1137         } else {
1138                 /* Channel was already available so we just need to add it back into the bridge */
1139                 underlying_channel = conference_bridge->playback_chan->tech->bridged_channel(conference_bridge->playback_chan, NULL);
1140                 ast_bridge_impart(conference_bridge->bridge, underlying_channel, NULL, NULL);
1141         }
1142
1143         /* The channel is all under our control, in goes the prompt */
1144         if (!ast_strlen_zero(filename)) {
1145                 ast_stream_and_wait(conference_bridge->playback_chan, filename, "");
1146         } else {
1147                 ast_say_number(conference_bridge->playback_chan, say_number, "", conference_bridge->playback_chan->language, NULL);
1148         }
1149
1150         ast_debug(1, "Departing underlying channel '%s' from bridge '%p'\n", underlying_channel->name, conference_bridge->bridge);
1151         ast_bridge_depart(conference_bridge->bridge, underlying_channel);
1152
1153         ast_mutex_unlock(&conference_bridge->playback_lock);
1154
1155         return 0;
1156 }
1157
1158 /*!
1159  * \brief Play sound file into conference bridge
1160  *
1161  * \param conference_bridge The conference bridge to play sound file into
1162  * \param filename Sound file to play
1163  *
1164  * \retval 0 success
1165  * \retval -1 failure
1166  */
1167 static int play_sound_file(struct conference_bridge *conference_bridge, const char *filename)
1168 {
1169         return play_sound_helper(conference_bridge, filename, 0);
1170 }
1171
1172 /*!
1173  * \brief Play number into the conference bridge
1174  *
1175  * \param conference_bridge The conference bridge to say the number into
1176  * \param number to say
1177  *
1178  * \retval 0 success
1179  * \retval -1 failure
1180  */
1181 static int play_sound_number(struct conference_bridge *conference_bridge, int say_number)
1182 {
1183         return play_sound_helper(conference_bridge, NULL, say_number);
1184 }
1185
1186 static void conf_handle_talker_destructor(void *pvt_data)
1187 {
1188         ast_free(pvt_data);
1189 }
1190
1191 static void conf_handle_talker_cb(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *pvt_data)
1192 {
1193         char *conf_name = pvt_data;
1194         int talking;
1195
1196         switch (bridge_channel->state) {
1197         case AST_BRIDGE_CHANNEL_STATE_START_TALKING:
1198                 talking = 1;
1199                 break;
1200         case AST_BRIDGE_CHANNEL_STATE_STOP_TALKING:
1201                 talking = 0;
1202                 break;
1203         default:
1204                 return; /* uhh this shouldn't happen, but bail if it does. */
1205         }
1206
1207         /* notify AMI someone is has either started or stopped talking */
1208         ast_manager_event(bridge_channel->chan, EVENT_FLAG_CALL, "ConfbridgeTalking",
1209               "Channel: %s\r\n"
1210               "Uniqueid: %s\r\n"
1211               "Conference: %s\r\n"
1212               "TalkingStatus: %s\r\n",
1213               bridge_channel->chan->name, bridge_channel->chan->uniqueid, conf_name, talking ? "on" : "off");
1214 }
1215
1216 static int conf_get_pin(struct ast_channel *chan, struct conference_bridge_user *conference_bridge_user)
1217 {
1218         char pin_guess[MAX_PIN+1] = { 0, };
1219         const char *pin = conference_bridge_user->u_profile.pin;
1220         char *tmp = pin_guess;
1221         int i, res;
1222         unsigned int len = MAX_PIN ;
1223
1224         /* give them three tries to get the pin right */
1225         for (i = 0; i < 3; i++) {
1226                 if (ast_app_getdata(chan,
1227                         conf_get_sound(CONF_SOUND_GET_PIN, conference_bridge_user->b_profile.sounds),
1228                         tmp, len, 0) >= 0) {
1229                         if (!strcasecmp(pin, pin_guess)) {
1230                                 return 0;
1231                         }
1232                 }
1233                 ast_streamfile(chan,
1234                         conf_get_sound(CONF_SOUND_INVALID_PIN, conference_bridge_user->b_profile.sounds),
1235                         chan->language);
1236                 res = ast_waitstream(chan, AST_DIGIT_ANY);
1237                 if (res > 0) {
1238                         /* Account for digit already read during ivalid pin playback
1239                          * resetting pin buf. */
1240                         pin_guess[0] = res;
1241                         pin_guess[1] = '\0';
1242                         tmp = pin_guess + 1;
1243                         len = MAX_PIN - 1;
1244                 } else {
1245                         /* reset pin buf as empty buffer. */
1246                         tmp = pin_guess;
1247                         len = MAX_PIN;
1248                 }
1249         }
1250         return -1;
1251 }
1252
1253 static int conf_rec_name(struct conference_bridge_user *user, const char *conf_name)
1254 {
1255         char destdir[PATH_MAX];
1256         int res;
1257         int duration = 20;
1258
1259         snprintf(destdir, sizeof(destdir), "%s/confbridge", ast_config_AST_SPOOL_DIR);
1260
1261         if (ast_mkdir(destdir, 0777) != 0) {
1262                 ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", destdir, strerror(errno));
1263                 return -1;
1264         }
1265         snprintf(user->name_rec_location, sizeof(user->name_rec_location),
1266                  "%s/confbridge-name-%s-%s", destdir,
1267                  conf_name, user->chan->uniqueid);
1268
1269         res = ast_play_and_record(user->chan,
1270                 "vm-rec-name",
1271                 user->name_rec_location,
1272                 10,
1273                 "sln",
1274                 &duration,
1275                 ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE),
1276                 0,
1277                 NULL);
1278
1279         if (res == -1) {
1280                 user->name_rec_location[0] = '\0';
1281                 return -1;
1282         }
1283         return 0;
1284 }
1285
1286 /*! \brief The ConfBridge application */
1287 static int confbridge_exec(struct ast_channel *chan, const char *data)
1288 {
1289         int res = 0, volume_adjustments[2];
1290         int quiet = 0;
1291         char *parse;
1292         const char *b_profile_name = DEFAULT_BRIDGE_PROFILE;
1293         const char *u_profile_name = DEFAULT_USER_PROFILE;
1294         struct conference_bridge *conference_bridge = NULL;
1295         struct conference_bridge_user conference_bridge_user = {
1296                 .chan = chan,
1297                 .tech_args.talking_threshold = DEFAULT_TALKING_THRESHOLD,
1298                 .tech_args.silence_threshold = DEFAULT_SILENCE_THRESHOLD,
1299                 .tech_args.drop_silence = 0,
1300         };
1301         AST_DECLARE_APP_ARGS(args,
1302                 AST_APP_ARG(conf_name);
1303                 AST_APP_ARG(b_profile_name);
1304                 AST_APP_ARG(u_profile_name);
1305                 AST_APP_ARG(menu_name);
1306         );
1307         ast_bridge_features_init(&conference_bridge_user.features);
1308
1309         if (chan->_state != AST_STATE_UP) {
1310                 ast_answer(chan);
1311         }
1312
1313         if (ast_strlen_zero(data)) {
1314                 ast_log(LOG_WARNING, "%s requires an argument (conference name[,options])\n", app);
1315                 res = -1; /* invalid PIN */
1316                 goto confbridge_cleanup;
1317         }
1318
1319         /* We need to make a copy of the input string if we are going to modify it! */
1320         parse = ast_strdupa(data);
1321
1322         AST_STANDARD_APP_ARGS(args, parse);
1323
1324         /* bridge profile name */
1325         if (args.argc > 1 && !ast_strlen_zero(args.b_profile_name)) {
1326                 b_profile_name = args.b_profile_name;
1327         }
1328         if (!conf_find_bridge_profile(chan, b_profile_name, &conference_bridge_user.b_profile)) {
1329                 ast_log(LOG_WARNING, "Conference bridge profile %s does not exist\n", b_profile_name);
1330                 res = -1;
1331                 goto confbridge_cleanup;
1332         }
1333
1334         /* user profile name */
1335         if (args.argc > 2 && !ast_strlen_zero(args.u_profile_name)) {
1336                 u_profile_name = args.u_profile_name;
1337         }
1338
1339         if (!conf_find_user_profile(chan, u_profile_name, &conference_bridge_user.u_profile)) {
1340                 ast_log(LOG_WARNING, "Conference user profile %s does not exist\n", u_profile_name);
1341                 res = -1;
1342                 goto confbridge_cleanup;
1343         }
1344         quiet = ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_QUIET);
1345
1346         /* ask for a PIN immediately after finding user profile.  This has to be
1347          * prompted for requardless of quiet setting. */
1348         if (!ast_strlen_zero(conference_bridge_user.u_profile.pin)) {
1349                 if (conf_get_pin(chan, &conference_bridge_user)) {
1350                         res = -1; /* invalid PIN */
1351                         goto confbridge_cleanup;
1352                 }
1353         }
1354
1355         /* See if we need them to record a intro name */
1356         if (!quiet && ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_ANNOUNCE_JOIN_LEAVE)) {
1357                 conf_rec_name(&conference_bridge_user, args.conf_name);
1358         }
1359
1360         /* menu name */
1361         if (args.argc > 3 && !ast_strlen_zero(args.menu_name)) {
1362                 ast_copy_string(conference_bridge_user.menu_name, args.menu_name, sizeof(conference_bridge_user.menu_name));
1363                 if (conf_set_menu_to_user(conference_bridge_user.menu_name, &conference_bridge_user)) {
1364                         ast_log(LOG_WARNING, "Conference menu %s does not exist and can not be applied to confbridge user.\n",
1365                                 args.menu_name);
1366                         res = -1; /* invalid PIN */
1367                         goto confbridge_cleanup;
1368                 }
1369         }
1370
1371         /* Set if DTMF should pass through for this user or not */
1372         if (ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_DTMF_PASS)) {
1373                 conference_bridge_user.features.dtmf_passthrough = 1;
1374         }
1375
1376         /* Set dsp threshold values if present */
1377         if (conference_bridge_user.u_profile.talking_threshold) {
1378                 conference_bridge_user.tech_args.talking_threshold = conference_bridge_user.u_profile.talking_threshold;
1379         }
1380         if (conference_bridge_user.u_profile.silence_threshold) {
1381                 conference_bridge_user.tech_args.silence_threshold = conference_bridge_user.u_profile.silence_threshold;
1382         }
1383
1384         /* Set a talker indicate call back if talking detection is requested */
1385         if (ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_TALKER_DETECT)) {
1386                 char *conf_name = ast_strdup(args.conf_name); /* this is freed during feature cleanup */
1387                 if (!(conf_name)) {
1388                         res = -1; /* invalid PIN */
1389                         goto confbridge_cleanup;
1390                 }
1391                 ast_bridge_features_set_talk_detector(&conference_bridge_user.features,
1392                         conf_handle_talker_cb,
1393                         conf_handle_talker_destructor,
1394                         conf_name);
1395         }
1396
1397         /* Look for a conference bridge matching the provided name */
1398         if (!(conference_bridge = join_conference_bridge(args.conf_name, &conference_bridge_user))) {
1399                 res = -1; /* invalid PIN */
1400                 goto confbridge_cleanup;
1401         }
1402
1403         /* Keep a copy of volume adjustments so we can restore them later if need be */
1404         volume_adjustments[0] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_READ);
1405         volume_adjustments[1] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_WRITE);
1406
1407         /* If the caller should be joined already muted, make it so */
1408         if (ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_STARTMUTED)) {
1409                 conference_bridge_user.features.mute = 1;
1410         }
1411
1412         if (ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_DROP_SILENCE)) {
1413                 conference_bridge_user.tech_args.drop_silence = 1;
1414         }
1415
1416         if (ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_JITTERBUFFER)) {
1417                 char *func_jb;
1418                 if ((func_jb = ast_module_helper("", "func_jitterbuffer", 0, 0, 0, 0))) {
1419                         ast_free(func_jb);
1420                         ast_func_write(chan, "JITTERBUFFER(adaptive)", "default");
1421                 }
1422         }
1423
1424         if (ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_DENOISE)) {
1425                 char *mod_speex;
1426                 /* Reduce background noise from each participant */
1427                 if ((mod_speex = ast_module_helper("", "codec_speex", 0, 0, 0, 0))) {
1428                         ast_free(mod_speex);
1429                         ast_func_write(chan, "DENOISE(rx)", "on");
1430                 }
1431         }
1432
1433         /* if this user has a intro, play it before entering */
1434         if (!ast_strlen_zero(conference_bridge_user.name_rec_location)) {
1435                 ast_autoservice_start(chan);
1436                 play_sound_file(conference_bridge, conference_bridge_user.name_rec_location);
1437                 play_sound_file(conference_bridge,
1438                         conf_get_sound(CONF_SOUND_HAS_JOINED, conference_bridge_user.b_profile.sounds));
1439                 ast_autoservice_stop(chan);
1440         }
1441
1442         /* Play the Join sound to both the conference and the user entering. */
1443         if (!quiet) {
1444                 const char *join_sound = conf_get_sound(CONF_SOUND_JOIN, conference_bridge_user.b_profile.sounds);
1445                 if (conference_bridge_user.playing_moh) {
1446                         ast_moh_stop(chan);
1447                 }
1448                 ast_stream_and_wait(chan, join_sound, "");
1449                 ast_autoservice_start(chan);
1450                 play_sound_file(conference_bridge, join_sound);
1451                 ast_autoservice_stop(chan);
1452                 if (conference_bridge_user.playing_moh) {
1453                         ast_moh_start(chan, conference_bridge_user.u_profile.moh_class, NULL);
1454                 }
1455         }
1456
1457         handle_video_on_join(conference_bridge, &conference_bridge_user);
1458
1459         /* Join our conference bridge for real */
1460         send_join_event(conference_bridge_user.chan, conference_bridge->name);
1461         ast_bridge_join(conference_bridge->bridge,
1462                 chan,
1463                 NULL,
1464                 &conference_bridge_user.features,
1465                 &conference_bridge_user.tech_args);
1466         send_leave_event(conference_bridge_user.chan, conference_bridge->name);
1467
1468
1469         handle_video_on_exit(conference_bridge, &conference_bridge_user);
1470
1471         /* if this user has a intro, play it when leaving */
1472         if (!quiet && !ast_strlen_zero(conference_bridge_user.name_rec_location)) {
1473                 ast_autoservice_start(chan);
1474                 play_sound_file(conference_bridge, conference_bridge_user.name_rec_location);
1475                 play_sound_file(conference_bridge,
1476                         conf_get_sound(CONF_SOUND_HAS_LEFT, conference_bridge_user.b_profile.sounds));
1477                 ast_autoservice_stop(chan);
1478         }
1479
1480         /* play the leave sound */
1481         if (!quiet) {
1482                 const char *leave_sound = conf_get_sound(CONF_SOUND_LEAVE, conference_bridge_user.b_profile.sounds);
1483                 ast_autoservice_start(chan);
1484                 play_sound_file(conference_bridge, leave_sound);
1485                 ast_autoservice_stop(chan);
1486         }
1487
1488         /* Easy as pie, depart this channel from the conference bridge */
1489         leave_conference_bridge(conference_bridge, &conference_bridge_user);
1490         conference_bridge = NULL;
1491
1492         /* If the user was kicked from the conference play back the audio prompt for it */
1493         if (!quiet && conference_bridge_user.kicked) {
1494                 res = ast_stream_and_wait(chan,
1495                         conf_get_sound(CONF_SOUND_KICKED, conference_bridge_user.b_profile.sounds),
1496                         "");
1497         }
1498
1499         /* Restore volume adjustments to previous values in case they were changed */
1500         if (volume_adjustments[0]) {
1501                 ast_audiohook_volume_set(chan, AST_AUDIOHOOK_DIRECTION_READ, volume_adjustments[0]);
1502         }
1503         if (volume_adjustments[1]) {
1504                 ast_audiohook_volume_set(chan, AST_AUDIOHOOK_DIRECTION_WRITE, volume_adjustments[1]);
1505         }
1506
1507         if (!ast_strlen_zero(conference_bridge_user.name_rec_location)) {
1508                 ast_filedelete(conference_bridge_user.name_rec_location, NULL);
1509         }
1510
1511 confbridge_cleanup:
1512         ast_bridge_features_cleanup(&conference_bridge_user.features);
1513         conf_bridge_profile_destroy(&conference_bridge_user.b_profile);
1514         return res;
1515 }
1516
1517 static int action_toggle_mute(struct conference_bridge *conference_bridge,
1518         struct conference_bridge_user *conference_bridge_user,
1519         struct ast_channel *chan)
1520 {
1521         /* Mute or unmute yourself, note we only allow manipulation if they aren't waiting for a marked user or if marked users exist */
1522         if (!ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_WAITMARKED) || conference_bridge->markedusers) {
1523                 conference_bridge_user->features.mute = (!conference_bridge_user->features.mute ? 1 : 0);
1524         }
1525         return ast_stream_and_wait(chan, (conference_bridge_user->features.mute ?
1526                 conf_get_sound(CONF_SOUND_MUTED, conference_bridge_user->b_profile.sounds) :
1527                 conf_get_sound(CONF_SOUND_UNMUTED, conference_bridge_user->b_profile.sounds)),
1528                 "");
1529 }
1530
1531 static int action_playback(struct ast_bridge_channel *bridge_channel, const char *playback_file)
1532 {
1533         char *file_copy = ast_strdupa(playback_file);
1534         char *file = NULL;
1535
1536         while ((file = strsep(&file_copy, "&"))) {
1537                 if (ast_stream_and_wait(bridge_channel->chan, file, "")) {
1538                         ast_log(LOG_WARNING, "Failed to playback file %s to channel\n", file);
1539                         return -1;
1540                 }
1541         }
1542         return 0;
1543 }
1544
1545 static int action_playback_and_continue(struct conference_bridge *conference_bridge,
1546         struct conference_bridge_user *conference_bridge_user,
1547         struct ast_bridge_channel *bridge_channel,
1548         struct conf_menu *menu,
1549         const char *playback_file,
1550         const char *cur_dtmf,
1551         int *stop_prompts)
1552 {
1553         int i;
1554         int digit = 0;
1555         char dtmf[MAXIMUM_DTMF_FEATURE_STRING];
1556         struct conf_menu_entry new_menu_entry = { { 0, }, };
1557         char *file_copy = ast_strdupa(playback_file);
1558         char *file = NULL;
1559
1560         while ((file = strsep(&file_copy, "&"))) {
1561                 if (ast_streamfile(bridge_channel->chan, file, bridge_channel->chan->language)) {
1562                         ast_log(LOG_WARNING, "Failed to playback file %s to channel\n", file);
1563                         return -1;
1564                 }
1565
1566                 /* now wait for more digits. */
1567                 if (!(digit = ast_waitstream(bridge_channel->chan, AST_DIGIT_ANY))) {
1568                         /* streaming finished and no DTMF was entered */
1569                         continue;
1570                 } else if (digit == -1) {
1571                         /* error */
1572                         return -1;
1573                 } else {
1574                         break; /* dtmf was entered */
1575                 }
1576         }
1577         if (!digit) {
1578                 /* streaming finished on all files and no DTMF was entered */
1579                 return -1;
1580         }
1581         ast_stopstream(bridge_channel->chan);
1582
1583         /* If we get here, then DTMF has been entered, This means no
1584          * additional prompts should be played for this menu entry */
1585         *stop_prompts = 1;
1586
1587         /* If a digit was pressed during the payback, update
1588          * the dtmf string and look for a new menu entry in the
1589          * menu structure */
1590         ast_copy_string(dtmf, cur_dtmf, sizeof(dtmf));
1591         for (i = 0; i < (MAXIMUM_DTMF_FEATURE_STRING - 1); i++) {
1592                 dtmf[i] = cur_dtmf[i];
1593                 if (!dtmf[i]) {
1594                         dtmf[i] = (char) digit;
1595                         dtmf[i + 1] = '\0';
1596                         i = -1;
1597                         break;
1598                 }
1599         }
1600         /* If i is not -1 then the new dtmf digit was _NOT_ added to the string.
1601          * If this is the case, no new DTMF sequence should be looked for. */
1602         if (i != -1) {
1603                 return 0;
1604         }
1605
1606         if (conf_find_menu_entry_by_sequence(dtmf, menu, &new_menu_entry)) {
1607                 execute_menu_entry(conference_bridge,
1608                         conference_bridge_user,
1609                         bridge_channel,
1610                         &new_menu_entry, menu);
1611                 conf_menu_entry_destroy(&new_menu_entry);
1612         }
1613         return 0;
1614 }
1615
1616 static int action_kick_last(struct conference_bridge *conference_bridge,
1617         struct ast_bridge_channel *bridge_channel,
1618         struct conference_bridge_user *conference_bridge_user)
1619 {
1620         struct conference_bridge_user *last_participant = NULL;
1621         int isadmin = ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_ADMIN);
1622
1623         if (!isadmin) {
1624                 ast_stream_and_wait(bridge_channel->chan,
1625                         conf_get_sound(CONF_SOUND_ERROR_MENU, conference_bridge_user->b_profile.sounds),
1626                         "");
1627                 ast_log(LOG_WARNING, "Only admin users can use the kick_last menu action. Channel %s of conf %s is not an admin.\n",
1628                         bridge_channel->chan->name,
1629                         conference_bridge->name);
1630                 return -1;
1631         }
1632
1633         ao2_lock(conference_bridge);
1634         if (((last_participant = AST_LIST_LAST(&conference_bridge->users_list)) == conference_bridge_user)
1635                 || (ast_test_flag(&last_participant->u_profile, USER_OPT_ADMIN))) {
1636                 ao2_unlock(conference_bridge);
1637                 ast_stream_and_wait(bridge_channel->chan,
1638                         conf_get_sound(CONF_SOUND_ERROR_MENU, conference_bridge_user->b_profile.sounds),
1639                         "");
1640         } else if (last_participant) {
1641                 last_participant->kicked = 1;
1642                 ast_bridge_remove(conference_bridge->bridge, last_participant->chan);
1643                 ao2_unlock(conference_bridge);
1644         }
1645         return 0;
1646 }
1647
1648 static int action_dialplan_exec(struct ast_bridge_channel *bridge_channel, struct conf_menu_action *menu_action)
1649 {
1650         struct ast_pbx_args args;
1651         struct ast_pbx *pbx;
1652         char *exten;
1653         char *context;
1654         int priority;
1655         int res;
1656
1657         memset(&args, 0, sizeof(args));
1658         args.no_hangup_chan = 1;
1659
1660         ast_channel_lock(bridge_channel->chan);
1661
1662         /*save off*/
1663         exten = ast_strdupa(bridge_channel->chan->exten);
1664         context = ast_strdupa(bridge_channel->chan->context);
1665         priority = bridge_channel->chan->priority;
1666         pbx = bridge_channel->chan->pbx;
1667         bridge_channel->chan->pbx = NULL;
1668
1669         /*set new*/
1670         ast_copy_string(bridge_channel->chan->exten, menu_action->data.dialplan_args.exten, sizeof(bridge_channel->chan->exten));
1671         ast_copy_string(bridge_channel->chan->context, menu_action->data.dialplan_args.context, sizeof(bridge_channel->chan->context));
1672         bridge_channel->chan->priority = menu_action->data.dialplan_args.priority;
1673
1674         ast_channel_unlock(bridge_channel->chan);
1675
1676         /*execute*/
1677         res = ast_pbx_run_args(bridge_channel->chan, &args);
1678
1679         /*restore*/
1680         ast_channel_lock(bridge_channel->chan);
1681
1682         ast_copy_string(bridge_channel->chan->exten, exten, sizeof(bridge_channel->chan->exten));
1683         ast_copy_string(bridge_channel->chan->context, context, sizeof(bridge_channel->chan->context));
1684         bridge_channel->chan->priority = priority;
1685         bridge_channel->chan->pbx = pbx;
1686
1687         ast_channel_unlock(bridge_channel->chan);
1688
1689         return res;
1690 }
1691
1692 static int execute_menu_entry(struct conference_bridge *conference_bridge,
1693         struct conference_bridge_user *conference_bridge_user,
1694         struct ast_bridge_channel *bridge_channel,
1695         struct conf_menu_entry *menu_entry,
1696         struct conf_menu *menu)
1697 {
1698         struct conf_menu_action *menu_action;
1699         int isadmin = ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_ADMIN);
1700         int stop_prompts = 0;
1701         int res = 0;
1702
1703         AST_LIST_TRAVERSE(&menu_entry->actions, menu_action, action) {
1704                 switch (menu_action->id) {
1705                 case MENU_ACTION_TOGGLE_MUTE:
1706                         res |= action_toggle_mute(conference_bridge,
1707                                 conference_bridge_user,
1708                                 bridge_channel->chan);
1709                         break;
1710                 case MENU_ACTION_PLAYBACK:
1711                         if (!stop_prompts) {
1712                                 res |= action_playback(bridge_channel, menu_action->data.playback_file);
1713                         }
1714                         break;
1715                 case MENU_ACTION_RESET_LISTENING:
1716                         ast_audiohook_volume_set(conference_bridge_user->chan, AST_AUDIOHOOK_DIRECTION_WRITE, 0);
1717                         break;
1718                 case MENU_ACTION_RESET_TALKING:
1719                         ast_audiohook_volume_set(conference_bridge_user->chan, AST_AUDIOHOOK_DIRECTION_READ, 0);
1720                         break;
1721                 case MENU_ACTION_INCREASE_LISTENING:
1722                         ast_audiohook_volume_adjust(conference_bridge_user->chan,
1723                                 AST_AUDIOHOOK_DIRECTION_WRITE, 1);
1724                         break;
1725                 case MENU_ACTION_DECREASE_LISTENING:
1726                         ast_audiohook_volume_adjust(conference_bridge_user->chan,
1727                                 AST_AUDIOHOOK_DIRECTION_WRITE, -1);
1728                         break;
1729                 case MENU_ACTION_INCREASE_TALKING:
1730                         ast_audiohook_volume_adjust(conference_bridge_user->chan,
1731                                 AST_AUDIOHOOK_DIRECTION_READ, 1);
1732                         break;
1733                 case MENU_ACTION_DECREASE_TALKING:
1734                         ast_audiohook_volume_adjust(conference_bridge_user->chan,
1735                                 AST_AUDIOHOOK_DIRECTION_READ, -1);
1736                         break;
1737                 case MENU_ACTION_PLAYBACK_AND_CONTINUE:
1738                         if (!(stop_prompts)) {
1739                                 res |= action_playback_and_continue(conference_bridge,
1740                                         conference_bridge_user,
1741                                         bridge_channel,
1742                                         menu,
1743                                         menu_action->data.playback_file,
1744                                         menu_entry->dtmf,
1745                                         &stop_prompts);
1746                         }
1747                         break;
1748                 case MENU_ACTION_DIALPLAN_EXEC:
1749                         res |= action_dialplan_exec(bridge_channel, menu_action);
1750                         break;
1751                 case MENU_ACTION_ADMIN_TOGGLE_LOCK:
1752                         if (!isadmin) {
1753                                 break;
1754                         }
1755                         conference_bridge->locked = (!conference_bridge->locked ? 1 : 0);
1756                         res |= ast_stream_and_wait(bridge_channel->chan,
1757                                 (conference_bridge->locked ?
1758                                 conf_get_sound(CONF_SOUND_LOCKED_NOW, conference_bridge_user->b_profile.sounds) :
1759                                 conf_get_sound(CONF_SOUND_UNLOCKED_NOW, conference_bridge_user->b_profile.sounds)),
1760                                 "");
1761
1762                         break;
1763                 case MENU_ACTION_ADMIN_KICK_LAST:
1764                         res |= action_kick_last(conference_bridge, bridge_channel, conference_bridge_user);
1765                         break;
1766                 case MENU_ACTION_LEAVE:
1767                         ao2_lock(conference_bridge);
1768                         ast_bridge_remove(conference_bridge->bridge, bridge_channel->chan);
1769                         ao2_unlock(conference_bridge);
1770                         break;
1771                 case MENU_ACTION_NOOP:
1772                         break;
1773                 case MENU_ACTION_SET_SINGLE_VIDEO_SRC:
1774                         ao2_lock(conference_bridge);
1775                         ast_bridge_set_single_src_video_mode(conference_bridge->bridge, bridge_channel->chan);
1776                         ao2_unlock(conference_bridge);
1777                         break;
1778                 }
1779         }
1780         return res;
1781 }
1782
1783 int conf_handle_dtmf(struct ast_bridge_channel *bridge_channel,
1784         struct conference_bridge_user *conference_bridge_user,
1785         struct conf_menu_entry *menu_entry,
1786         struct conf_menu *menu)
1787 {
1788         struct conference_bridge *conference_bridge = conference_bridge_user->conference_bridge;
1789
1790         /* See if music on hold is playing */
1791         ao2_lock(conference_bridge);
1792         if (conference_bridge_user->playing_moh) {
1793                 /* MOH is going, let's stop it */
1794                 ast_moh_stop(bridge_channel->chan);
1795         }
1796         ao2_unlock(conference_bridge);
1797
1798         /* execute the list of actions associated with this menu entry */
1799         execute_menu_entry(conference_bridge, conference_bridge_user, bridge_channel, menu_entry, menu);
1800
1801         /* See if music on hold needs to be started back up again */
1802         ao2_lock(conference_bridge);
1803         if (conference_bridge_user->playing_moh) {
1804                 ast_moh_start(bridge_channel->chan, conference_bridge_user->u_profile.moh_class, NULL);
1805         }
1806         ao2_unlock(conference_bridge);
1807
1808         return 0;
1809 }
1810
1811 static char *complete_confbridge_name(const char *line, const char *word, int pos, int state)
1812 {
1813         int which = 0;
1814         struct conference_bridge *bridge = NULL;
1815         char *res = NULL;
1816         int wordlen = strlen(word);
1817         struct ao2_iterator i;
1818
1819         i = ao2_iterator_init(conference_bridges, 0);
1820         while ((bridge = ao2_iterator_next(&i))) {
1821                 if (!strncasecmp(bridge->name, word, wordlen) && ++which > state) {
1822                         res = ast_strdup(bridge->name);
1823                         ao2_ref(bridge, -1);
1824                         break;
1825                 }
1826                 ao2_ref(bridge, -1);
1827         }
1828         ao2_iterator_destroy(&i);
1829
1830         return res;
1831 }
1832
1833 static char *handle_cli_confbridge_kick(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1834 {
1835         struct conference_bridge *bridge = NULL;
1836         struct conference_bridge tmp;
1837         struct conference_bridge_user *participant = NULL;
1838
1839         switch (cmd) {
1840         case CLI_INIT:
1841                 e->command = "confbridge kick";
1842                 e->usage =
1843                         "Usage: confbridge kick <conference> <channel>\n"
1844                         "       Kicks a channel out of the conference bridge.\n";
1845                 return NULL;
1846         case CLI_GENERATE:
1847                 if (a->pos == 2) {
1848                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
1849                 }
1850                 /*
1851                 if (a->pos == 3) {
1852                         return complete_confbridge_channel(a->line, a->word, a->pos, a->n);
1853                 }
1854                 */
1855                 return NULL;
1856         }
1857
1858         if (a->argc != 4) {
1859                 return CLI_SHOWUSAGE;
1860         }
1861
1862         ast_copy_string(tmp.name, a->argv[2], sizeof(tmp.name));
1863         bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
1864         if (!bridge) {
1865                 ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
1866                 return CLI_SUCCESS;
1867         }
1868         ao2_lock(bridge);
1869         AST_LIST_TRAVERSE(&bridge->users_list, participant, list) {
1870                 if (!strncmp(a->argv[3], participant->chan->name, strlen(participant->chan->name))) {
1871                         break;
1872                 }
1873         }
1874         if (participant) {
1875                 ast_cli(a->fd, "Kicking %s from confbridge %s\n", participant->chan->name, bridge->name);
1876                 participant->kicked = 1;
1877                 ast_bridge_remove(bridge->bridge, participant->chan);
1878         }
1879         ao2_unlock(bridge);
1880         ao2_ref(bridge, -1);
1881         return CLI_SUCCESS;
1882 }
1883
1884 static char *handle_cli_confbridge_list(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1885 {
1886         struct ao2_iterator i;
1887         struct conference_bridge *bridge = NULL;
1888         struct conference_bridge tmp;
1889         struct conference_bridge_user *participant = NULL;
1890
1891         switch (cmd) {
1892         case CLI_INIT:
1893                 e->command = "confbridge list";
1894                 e->usage =
1895                         "Usage: confbridge list [<name>]\n"
1896                         "       Lists all currently active conference bridges.\n";
1897                 return NULL;
1898         case CLI_GENERATE:
1899                 if (a->pos == 2) {
1900                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
1901                 }
1902                 return NULL;
1903         }
1904
1905         if (a->argc == 2) {
1906                 ast_cli(a->fd, "Conference Bridge Name           Users  Marked Locked?\n");
1907                 ast_cli(a->fd, "================================ ====== ====== ========\n");
1908                 i = ao2_iterator_init(conference_bridges, 0);
1909                 while ((bridge = ao2_iterator_next(&i))) {
1910                         ast_cli(a->fd, "%-32s %6i %6i %s\n", bridge->name, bridge->users, bridge->markedusers, (bridge->locked ? "locked" : "unlocked"));
1911                         ao2_ref(bridge, -1);
1912                 }
1913                 ao2_iterator_destroy(&i);
1914                 return CLI_SUCCESS;
1915         }
1916
1917         if (a->argc == 3) {
1918                 ast_copy_string(tmp.name, a->argv[2], sizeof(tmp.name));
1919                 bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
1920                 if (!bridge) {
1921                         ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
1922                         return CLI_SUCCESS;
1923                 }
1924                 ast_cli(a->fd, "Channel                       User Profile     Bridge Profile   Menu\n");
1925                 ast_cli(a->fd, "============================= ================ ================ ================\n");
1926                 ao2_lock(bridge);
1927                 AST_LIST_TRAVERSE(&bridge->users_list, participant, list) {
1928                         ast_cli(a->fd, "%-29s ", participant->chan->name);
1929                         ast_cli(a->fd, "%-17s", participant->u_profile.name);
1930                         ast_cli(a->fd, "%-17s", participant->b_profile.name);
1931                         ast_cli(a->fd, "%-17s", participant->menu_name);
1932                         ast_cli(a->fd, "\n");
1933                 }
1934                 ao2_unlock(bridge);
1935                 ao2_ref(bridge, -1);
1936                 return CLI_SUCCESS;
1937         }
1938
1939         return CLI_SHOWUSAGE;
1940 }
1941
1942 /* \internal
1943  * \brief finds a conference by name and locks/unlocks.
1944  *
1945  * \retval 0 success
1946  * \retval -1 conference not found
1947  */
1948 static int generic_lock_unlock_helper(int lock, const char *conference)
1949 {
1950         struct conference_bridge *bridge = NULL;
1951         struct conference_bridge tmp;
1952         int res = 0;
1953
1954         ast_copy_string(tmp.name, conference, sizeof(tmp.name));
1955         bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
1956         if (!bridge) {
1957                 return -1;
1958         }
1959         ao2_lock(bridge);
1960         bridge->locked = lock;
1961         ao2_unlock(bridge);
1962         ao2_ref(bridge, -1);
1963
1964         return res;
1965 }
1966
1967 /* \internal
1968  * \brief finds a conference user by channel name and mutes/unmutes them.
1969  *
1970  * \retval 0 success
1971  * \retval -1 conference not found
1972  * \retval -2 user not found
1973  */
1974 static int generic_mute_unmute_helper(int mute, const char *conference, const char *user)
1975 {
1976         struct conference_bridge *bridge = NULL;
1977         struct conference_bridge tmp;
1978         struct conference_bridge_user *participant = NULL;
1979         int res = 0;
1980         ast_copy_string(tmp.name, conference, sizeof(tmp.name));
1981         bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
1982         if (!bridge) {
1983                 return -1;
1984         }
1985         ao2_lock(bridge);
1986         AST_LIST_TRAVERSE(&bridge->users_list, participant, list) {
1987                 if (!strncmp(user, participant->chan->name, strlen(user))) {
1988                         break;
1989                 }
1990         }
1991         if (participant) {
1992                 participant->features.mute = mute;
1993         } else {
1994                 res = -2;;
1995         }
1996         ao2_unlock(bridge);
1997         ao2_ref(bridge, -1);
1998
1999         return res;
2000 }
2001
2002 static int cli_mute_unmute_helper(int mute, struct ast_cli_args *a)
2003 {
2004         int res = generic_mute_unmute_helper(mute, a->argv[2], a->argv[3]);
2005
2006         if (res == -1) {
2007                 ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
2008                 return -1;
2009         } else if (res == -2) {
2010                 ast_cli(a->fd, "No channel named '%s' found in conference %s\n", a->argv[3], a->argv[2]);
2011                 return -1;
2012         }
2013         ast_cli(a->fd, "%s %s from confbridge %s\n", mute ? "Muting" : "Unmuting", a->argv[3], a->argv[2]);
2014         return 0;
2015 }
2016
2017 static char *handle_cli_confbridge_mute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2018 {
2019         switch (cmd) {
2020         case CLI_INIT:
2021                 e->command = "confbridge mute";
2022                 e->usage =
2023                         "Usage: confbridge mute <conference> <channel>\n";
2024                 return NULL;
2025         case CLI_GENERATE:
2026                 if (a->pos == 2) {
2027                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
2028                 }
2029                 return NULL;
2030         }
2031         if (a->argc != 4) {
2032                 return CLI_SHOWUSAGE;
2033         }
2034
2035         cli_mute_unmute_helper(1, a);
2036
2037         return CLI_SUCCESS;
2038 }
2039
2040 static char *handle_cli_confbridge_unmute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2041 {
2042         switch (cmd) {
2043         case CLI_INIT:
2044                 e->command = "confbridge unmute";
2045                 e->usage =
2046                         "Usage: confbridge unmute <conference> <channel>\n";
2047                 return NULL;
2048         case CLI_GENERATE:
2049                 if (a->pos == 2) {
2050                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
2051                 }
2052                 return NULL;
2053         }
2054         if (a->argc != 4) {
2055                 return CLI_SHOWUSAGE;
2056         }
2057
2058         cli_mute_unmute_helper(0, a);
2059
2060         return CLI_SUCCESS;
2061 }
2062
2063 static char *handle_cli_confbridge_lock(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2064 {
2065         switch (cmd) {
2066         case CLI_INIT:
2067                 e->command = "confbridge lock";
2068                 e->usage =
2069                         "Usage: confbridge lock <conference>\n";
2070                 return NULL;
2071         case CLI_GENERATE:
2072                 if (a->pos == 2) {
2073                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
2074                 }
2075                 return NULL;
2076         }
2077         if (a->argc != 3) {
2078                 return CLI_SHOWUSAGE;
2079         }
2080         if (generic_lock_unlock_helper(1, a->argv[2])) {
2081                 ast_cli(a->fd, "Conference %s is not found\n", a->argv[2]);
2082         } else {
2083                 ast_cli(a->fd, "Conference %s is locked.\n", a->argv[2]);
2084         }
2085         return CLI_SUCCESS;
2086 }
2087
2088 static char *handle_cli_confbridge_unlock(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2089 {
2090         switch (cmd) {
2091         case CLI_INIT:
2092                 e->command = "confbridge unlock";
2093                 e->usage =
2094                         "Usage: confbridge unlock <conference>\n";
2095                 return NULL;
2096         case CLI_GENERATE:
2097                 if (a->pos == 2) {
2098                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
2099                 }
2100                 return NULL;
2101         }
2102         if (a->argc != 3) {
2103                 return CLI_SHOWUSAGE;
2104         }
2105         if (generic_lock_unlock_helper(0, a->argv[2])) {
2106                 ast_cli(a->fd, "Conference %s is not found\n", a->argv[2]);
2107         } else {
2108                 ast_cli(a->fd, "Conference %s is unlocked.\n", a->argv[2]);
2109         }
2110         return CLI_SUCCESS;
2111 }
2112
2113 static char *handle_cli_confbridge_start_record(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2114 {
2115         const char *rec_file = NULL;
2116         struct conference_bridge *bridge = NULL;
2117         struct conference_bridge tmp;
2118
2119         switch (cmd) {
2120         case CLI_INIT:
2121                 e->command = "confbridge record start";
2122                 e->usage =
2123                         "Usage: confbridge record start <conference> <file>\n"
2124                         "       <file> is optional, Otherwise the bridge profile\n"
2125                         "       record file will be used.  If the bridge profile\n"
2126                         "       has no record file specified, a file will automatically\n"
2127                         "       be generated in the monitor directory\n";
2128                 return NULL;
2129         case CLI_GENERATE:
2130                 if (a->pos == 3) {
2131                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
2132                 }
2133                 return NULL;
2134         }
2135         if (a->argc < 4) {
2136                 return CLI_SHOWUSAGE;
2137         }
2138         if (a->argc == 5) {
2139                 rec_file = a->argv[4];
2140         }
2141
2142         ast_copy_string(tmp.name, a->argv[3], sizeof(tmp.name));
2143         bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
2144         if (!bridge) {
2145                 ast_cli(a->fd, "Conference not found.\n");
2146                 return CLI_FAILURE;
2147         }
2148         if (conf_is_recording(bridge)) {
2149                 ast_cli(a->fd, "Conference is already being recorded.\n");
2150                 ao2_ref(bridge, -1);
2151                 return CLI_SUCCESS;
2152         }
2153         if (!ast_strlen_zero(rec_file)) {
2154                 ao2_lock(bridge);
2155                 ast_copy_string(bridge->b_profile.rec_file, rec_file, sizeof(bridge->b_profile.rec_file));
2156                 ao2_unlock(bridge);
2157         }
2158         if (conf_start_record(bridge)) {
2159                 ast_cli(a->fd, "Could not start recording due to internal error.\n");
2160                 ao2_ref(bridge, -1);
2161                 return CLI_FAILURE;
2162         }
2163         ast_cli(a->fd, "Recording started\n");
2164         ao2_ref(bridge, -1);
2165         return CLI_SUCCESS;
2166 }
2167
2168 static char *handle_cli_confbridge_stop_record(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2169 {
2170         struct conference_bridge *bridge = NULL;
2171         struct conference_bridge tmp;
2172
2173         switch (cmd) {
2174         case CLI_INIT:
2175                 e->command = "confbridge record stop";
2176                 e->usage =
2177                         "Usage: confbridge record stop <conference>\n";
2178                 return NULL;
2179         case CLI_GENERATE:
2180                 if (a->pos == 3) {
2181                         return complete_confbridge_name(a->line, a->word, a->pos, a->n);
2182                 }
2183                 return NULL;
2184         }
2185         if (a->argc != 4) {
2186                 return CLI_SHOWUSAGE;
2187         }
2188
2189         ast_copy_string(tmp.name, a->argv[3], sizeof(tmp.name));
2190         bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
2191         if (!bridge) {
2192                 ast_cli(a->fd, "Conference not found.\n");
2193                 return CLI_SUCCESS;
2194         }
2195         conf_stop_record(bridge);
2196         ast_cli(a->fd, "Recording stopped.\n");
2197         ao2_ref(bridge, -1);
2198         return CLI_SUCCESS;
2199 }
2200
2201 static struct ast_cli_entry cli_confbridge[] = {
2202         AST_CLI_DEFINE(handle_cli_confbridge_list, "List conference bridges and participants."),
2203         AST_CLI_DEFINE(handle_cli_confbridge_kick, "Kick participants out of conference bridges."),
2204         AST_CLI_DEFINE(handle_cli_confbridge_mute, "Mute a participant."),
2205         AST_CLI_DEFINE(handle_cli_confbridge_unmute, "Mute a participant."),
2206         AST_CLI_DEFINE(handle_cli_confbridge_lock, "Lock a conference."),
2207         AST_CLI_DEFINE(handle_cli_confbridge_unlock, "Unlock a conference."),
2208         AST_CLI_DEFINE(handle_cli_confbridge_start_record, "Start recording a conference"),
2209         AST_CLI_DEFINE(handle_cli_confbridge_stop_record, "Stop recording a conference."),
2210 };
2211 static struct ast_custom_function confbridge_function = {
2212         .name = "CONFBRIDGE",
2213         .write = func_confbridge_helper,
2214 };
2215
2216 static int func_confbridge_info(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len);
2217 static struct ast_custom_function confbridge_info_function = {
2218         .name = "CONFBRIDGE_INFO",
2219         .read = func_confbridge_info,
2220 };
2221
2222 static int action_confbridgelist(struct mansession *s, const struct message *m)
2223 {
2224         const char *actionid = astman_get_header(m, "ActionID");
2225         const char *conference = astman_get_header(m, "Conference");
2226         struct conference_bridge_user *participant = NULL;
2227         struct conference_bridge *bridge = NULL;
2228         struct conference_bridge tmp;
2229         char id_text[80] = "";
2230         int total = 0;
2231
2232         if (!ast_strlen_zero(actionid)) {
2233                 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", actionid);
2234         }
2235         if (ast_strlen_zero(conference)) {
2236                 astman_send_error(s, m, "No Conference name provided.");
2237                 return 0;
2238         }
2239         if (!ao2_container_count(conference_bridges)) {
2240                 astman_send_error(s, m, "No active conferences.");
2241                 return 0;
2242         }
2243         ast_copy_string(tmp.name, conference, sizeof(tmp.name));
2244         bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
2245         if (!bridge) {
2246                 astman_send_error(s, m, "No Conference by that name found.");
2247                 return 0;
2248         }
2249
2250         astman_send_listack(s, m, "Confbridge user list will follow", "start");
2251
2252         ao2_lock(bridge);
2253         AST_LIST_TRAVERSE(&bridge->users_list, participant, list) {
2254                 total++;
2255                 astman_append(s,
2256                         "Event: ConfbridgeList\r\n"
2257                         "%s"
2258                         "Conference: %s\r\n"
2259                         "CallerIDNum: %s\r\n"
2260                         "CallerIDName: %s\r\n"
2261                         "Channel: %s\r\n"
2262                         "Admin: %s\r\n"
2263                         "MarkedUser: %s\r\n"
2264                         "\r\n",
2265                         id_text,
2266                         bridge->name,
2267                         S_COR(participant->chan->caller.id.number.valid, participant->chan->caller.id.number.str, "<unknown>"),
2268                         S_COR(participant->chan->caller.id.name.valid, participant->chan->caller.id.name.str, "<no name>"),
2269                         participant->chan->name,
2270                         ast_test_flag(&participant->u_profile, USER_OPT_ADMIN) ? "Yes" : "No",
2271                         ast_test_flag(&participant->u_profile, USER_OPT_MARKEDUSER) ? "Yes" : "No");
2272         }
2273         ao2_unlock(bridge);
2274         ao2_ref(bridge, -1);
2275
2276         astman_append(s,
2277         "Event: ConfbridgeListComplete\r\n"
2278         "EventList: Complete\r\n"
2279         "ListItems: %d\r\n"
2280         "%s"
2281         "\r\n", total, id_text);
2282
2283         return 0;
2284 }
2285
2286 static int action_confbridgelistrooms(struct mansession *s, const struct message *m)
2287 {
2288         const char *actionid = astman_get_header(m, "ActionID");
2289         struct conference_bridge *bridge = NULL;
2290         struct ao2_iterator i;
2291         char id_text[512] = "";
2292         int totalitems = 0;
2293
2294         if (!ast_strlen_zero(actionid)) {
2295                 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", actionid);
2296         }
2297
2298         if (!ao2_container_count(conference_bridges)) {
2299                 astman_send_error(s, m, "No active conferences.");
2300                 return 0;
2301         }
2302
2303         astman_send_listack(s, m, "Confbridge conferences will follow", "start");
2304
2305         /* Traverse the conference list */
2306         i = ao2_iterator_init(conference_bridges, 0);
2307         while ((bridge = ao2_iterator_next(&i))) {
2308                 totalitems++;
2309
2310                 ao2_lock(bridge);
2311                 astman_append(s,
2312                 "Event: ConfbridgeListRooms\r\n"
2313                 "%s"
2314                 "Conference: %s\r\n"
2315                 "Parties: %d\r\n"
2316                 "Marked: %d\r\n"
2317                 "Locked: %s\r\n"
2318                 "\r\n",
2319                 id_text,
2320                 bridge->name,
2321                 bridge->users,
2322                 bridge->markedusers,
2323                 bridge->locked ? "Yes" : "No"); 
2324                 ao2_unlock(bridge);
2325
2326                 ao2_ref(bridge, -1);
2327         }
2328         ao2_iterator_destroy(&i);
2329
2330         /* Send final confirmation */
2331         astman_append(s,
2332         "Event: ConfbridgeListRoomsComplete\r\n"
2333         "EventList: Complete\r\n"
2334         "ListItems: %d\r\n"
2335         "%s"
2336         "\r\n", totalitems, id_text);
2337         return 0;
2338 }
2339
2340 static int action_mute_unmute_helper(struct mansession *s, const struct message *m, int mute)
2341 {
2342         const char *conference = astman_get_header(m, "Conference");
2343         const char *channel = astman_get_header(m, "Channel");
2344         int res = 0;
2345
2346         if (ast_strlen_zero(conference)) {
2347                 astman_send_error(s, m, "No Conference name provided.");
2348                 return 0;
2349         }
2350         if (ast_strlen_zero(channel)) {
2351                 astman_send_error(s, m, "No channel name provided.");
2352                 return 0;
2353         }
2354         if (!ao2_container_count(conference_bridges)) {
2355                 astman_send_error(s, m, "No active conferences.");
2356                 return 0;
2357         }
2358
2359         res = generic_mute_unmute_helper(mute, conference, channel);
2360
2361         if (res == -1) {
2362                 astman_send_error(s, m, "No Conference by that name found.");
2363                 return 0;
2364         } else if (res == -2) {
2365                 astman_send_error(s, m, "No Channel by that name found in Conference.");
2366                 return 0;
2367         }
2368
2369         astman_send_ack(s, m, mute ? "User muted" : "User unmuted");
2370         return 0;
2371 }
2372
2373 static int action_confbridgeunmute(struct mansession *s, const struct message *m)
2374 {
2375         return action_mute_unmute_helper(s, m, 0);
2376 }
2377 static int action_confbridgemute(struct mansession *s, const struct message *m)
2378 {
2379         return action_mute_unmute_helper(s, m, 1);
2380 }
2381
2382 static int action_lock_unlock_helper(struct mansession *s, const struct message *m, int lock)
2383 {
2384         const char *conference = astman_get_header(m, "Conference");
2385         int res = 0;
2386
2387         if (ast_strlen_zero(conference)) {
2388                 astman_send_error(s, m, "No Conference name provided.");
2389                 return 0;
2390         }
2391         if (!ao2_container_count(conference_bridges)) {
2392                 astman_send_error(s, m, "No active conferences.");
2393                 return 0;
2394         }
2395         if ((res = generic_lock_unlock_helper(lock, conference))) {
2396                 astman_send_error(s, m, "No Conference by that name found.");
2397                 return 0;
2398         }
2399         astman_send_ack(s, m, lock ? "Conference locked" : "Conference unlocked");
2400         return 0;
2401 }
2402 static int action_confbridgeunlock(struct mansession *s, const struct message *m)
2403 {
2404         return action_lock_unlock_helper(s, m, 0);
2405 }
2406 static int action_confbridgelock(struct mansession *s, const struct message *m)
2407 {
2408         return action_lock_unlock_helper(s, m, 1);
2409 }
2410
2411 static int action_confbridgekick(struct mansession *s, const struct message *m)
2412 {
2413         const char *conference = astman_get_header(m, "Conference");
2414         const char *channel = astman_get_header(m, "Channel");
2415         struct conference_bridge_user *participant = NULL;
2416         struct conference_bridge *bridge = NULL;
2417         struct conference_bridge tmp;
2418         int found = 0;
2419
2420         if (ast_strlen_zero(conference)) {
2421                 astman_send_error(s, m, "No Conference name provided.");
2422                 return 0;
2423         }
2424         if (!ao2_container_count(conference_bridges)) {
2425                 astman_send_error(s, m, "No active conferences.");
2426                 return 0;
2427         }
2428         ast_copy_string(tmp.name, conference, sizeof(tmp.name));
2429         bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
2430         if (!bridge) {
2431                 astman_send_error(s, m, "No Conference by that name found.");
2432                 return 0;
2433         }
2434
2435         ao2_lock(bridge);
2436         AST_LIST_TRAVERSE(&bridge->users_list, participant, list) {
2437                 if (!strcasecmp(participant->chan->name, channel)) {
2438                         participant->kicked = 1;
2439                         ast_bridge_remove(bridge->bridge, participant->chan);
2440                         found = 1;
2441                         break;
2442                 }
2443         }
2444         ao2_unlock(bridge);
2445         ao2_ref(bridge, -1);
2446
2447         if (found) {
2448                 astman_send_ack(s, m, "User kicked");
2449         } else {
2450                 astman_send_error(s, m, "No Channel by that name found in Conference.");
2451         }
2452         return 0;
2453 }
2454
2455 static int action_confbridgestartrecord(struct mansession *s, const struct message *m)
2456 {
2457         const char *conference = astman_get_header(m, "Conference");
2458         const char *recordfile = astman_get_header(m, "RecordFile");
2459         struct conference_bridge *bridge = NULL;
2460         struct conference_bridge tmp;
2461
2462         if (ast_strlen_zero(conference)) {
2463                 astman_send_error(s, m, "No Conference name provided.");
2464                 return 0;
2465         }
2466         if (!ao2_container_count(conference_bridges)) {
2467                 astman_send_error(s, m, "No active conferences.");
2468                 return 0;
2469         }
2470
2471         ast_copy_string(tmp.name, conference, sizeof(tmp.name));
2472         bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
2473         if (!bridge) {
2474                 astman_send_error(s, m, "No Conference by that name found.");
2475                 return 0;
2476         }
2477
2478         if (conf_is_recording(bridge)) {
2479                 astman_send_error(s, m, "Conference is already being recorded.");
2480                 ao2_ref(bridge, -1);
2481                 return 0;
2482         }
2483
2484         if (!ast_strlen_zero(recordfile)) {
2485                 ao2_lock(bridge);
2486                 ast_copy_string(bridge->b_profile.rec_file, recordfile, sizeof(bridge->b_profile.rec_file));
2487                 ao2_unlock(bridge);
2488         }
2489
2490         if (conf_start_record(bridge)) {
2491                 astman_send_error(s, m, "Internal error starting conference recording.");
2492                 ao2_ref(bridge, -1);
2493                 return 0;
2494         }
2495
2496         ao2_ref(bridge, -1);
2497         astman_send_ack(s, m, "Conference Recording Started.");
2498         return 0;
2499 }
2500 static int action_confbridgestoprecord(struct mansession *s, const struct message *m)
2501 {
2502         const char *conference = astman_get_header(m, "Conference");
2503         struct conference_bridge *bridge = NULL;
2504         struct conference_bridge tmp;
2505
2506         if (ast_strlen_zero(conference)) {
2507                 astman_send_error(s, m, "No Conference name provided.");
2508                 return 0;
2509         }
2510         if (!ao2_container_count(conference_bridges)) {
2511                 astman_send_error(s, m, "No active conferences.");
2512                 return 0;
2513         }
2514
2515         ast_copy_string(tmp.name, conference, sizeof(tmp.name));
2516         bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
2517         if (!bridge) {
2518                 astman_send_error(s, m, "No Conference by that name found.");
2519                 return 0;
2520         }
2521
2522         if (conf_stop_record(bridge)) {
2523                 astman_send_error(s, m, "Internal error while stopping recording.");
2524                 ao2_ref(bridge, -1);
2525                 return 0;
2526         }
2527
2528         ao2_ref(bridge, -1);
2529         astman_send_ack(s, m, "Conference Recording Stopped.");
2530         return 0;
2531 }
2532
2533 static int action_confbridgesetsinglevideosrc(struct mansession *s, const struct message *m)
2534 {
2535         const char *conference = astman_get_header(m, "Conference");
2536         const char *channel = astman_get_header(m, "Channel");
2537         struct conference_bridge_user *participant = NULL;
2538         struct conference_bridge *bridge = NULL;
2539         struct conference_bridge tmp;
2540
2541         if (ast_strlen_zero(conference)) {
2542                 astman_send_error(s, m, "No Conference name provided.");
2543                 return 0;
2544         }
2545         if (ast_strlen_zero(channel)) {
2546                 astman_send_error(s, m, "No channel name provided.");
2547                 return 0;
2548         }
2549         if (!ao2_container_count(conference_bridges)) {
2550                 astman_send_error(s, m, "No active conferences.");
2551                 return 0;
2552         }
2553
2554         ast_copy_string(tmp.name, conference, sizeof(tmp.name));
2555         bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
2556         if (!bridge) {
2557                 astman_send_error(s, m, "No Conference by that name found.");
2558                 return 0;
2559         }
2560
2561         /* find channel and set as video src. */
2562         ao2_lock(bridge);
2563         AST_LIST_TRAVERSE(&bridge->users_list, participant, list) {
2564                 if (!strncmp(channel, participant->chan->name, strlen(channel))) {
2565                         ast_bridge_set_single_src_video_mode(bridge->bridge, participant->chan);
2566                         break;
2567                 }
2568         }
2569         ao2_unlock(bridge);
2570         ao2_ref(bridge, -1);
2571
2572         /* do not access participant after bridge unlock.  We are just
2573          * using this check to see if it was found or not */
2574         if (!participant) {
2575                 astman_send_error(s, m, "No channel by that name found in conference.");
2576                 return 0;
2577         }
2578         astman_send_ack(s, m, "Conference single video source set.");
2579         return 0;
2580 }
2581
2582 static int func_confbridge_info(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
2583 {
2584         char *parse = NULL;
2585         struct conference_bridge *bridge = NULL;
2586         struct conference_bridge_user *participant = NULL;
2587         struct conference_bridge tmp;
2588         int count = 0;
2589         AST_DECLARE_APP_ARGS(args,
2590                 AST_APP_ARG(type);
2591                 AST_APP_ARG(confno);
2592         );
2593
2594         /* parse all the required arguments and make sure they exist. */
2595         if (ast_strlen_zero(data)) {
2596                 return -1;
2597         }
2598         parse = ast_strdupa(data);
2599         AST_STANDARD_APP_ARGS(args, parse);
2600         if (ast_strlen_zero(args.confno) || ast_strlen_zero(args.type)) {
2601                 return -1;
2602         }
2603         if (!ao2_container_count(conference_bridges)) {
2604                 ast_log(LOG_ERROR, "No active conferneces.\n");
2605                 return -1;
2606         }
2607         ast_copy_string(tmp.name, args.confno, sizeof(tmp.name));
2608         bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
2609         if (!bridge) {
2610                 ast_log(LOG_ERROR, "Confernece '%s' not found.\n", args.confno);
2611                 return -1;
2612         }
2613
2614         /* get the correct count for the type requested */
2615         ao2_lock(bridge);
2616         if (!strncasecmp(args.type, "parties", 7)) {
2617                 AST_LIST_TRAVERSE(&bridge->users_list, participant, list) {
2618                         count++;
2619                 }
2620         } else if (!strncasecmp(args.type, "admins", 6)) {
2621                 AST_LIST_TRAVERSE(&bridge->users_list, participant, list) {
2622                         if (ast_test_flag(&participant->u_profile, USER_OPT_ADMIN)) {
2623                                 count++;
2624                         }
2625                 }
2626         } else if (!strncasecmp(args.type, "marked", 6)) {
2627                 AST_LIST_TRAVERSE(&bridge->users_list, participant, list) {
2628                         if (ast_test_flag(&participant->u_profile, USER_OPT_MARKEDUSER)) {
2629                                 count++;
2630                         }
2631                 }
2632         } else if (!strncasecmp(args.type, "locked", 6)) {
2633                 count = bridge->locked;
2634         } else {
2635                 ao2_unlock(bridge);
2636                 ao2_ref(bridge, -1);
2637                 return -1;
2638         }
2639         snprintf(buf, len, "%d", count);
2640         ao2_unlock(bridge);
2641         ao2_ref(bridge, -1);
2642         return 0;
2643 }
2644
2645 /*! \brief Called when module is being unloaded */
2646 static int unload_module(void)
2647 {
2648         int res = ast_unregister_application(app);
2649
2650         ast_custom_function_unregister(&confbridge_function);
2651         ast_custom_function_unregister(&confbridge_info_function);
2652
2653         ast_cli_unregister_multiple(cli_confbridge, sizeof(cli_confbridge) / sizeof(struct ast_cli_entry));
2654
2655         /* Get rid of the conference bridges container. Since we only allow dynamic ones none will be active. */
2656         ao2_ref(conference_bridges, -1);
2657
2658         conf_destroy_config();
2659
2660         ast_channel_unregister(&record_tech);
2661         record_tech.capabilities = ast_format_cap_destroy(record_tech.capabilities);
2662
2663         res |= ast_manager_unregister("ConfbridgeList");
2664         res |= ast_manager_unregister("ConfbridgeListRooms");
2665         res |= ast_manager_unregister("ConfbridgeMute");
2666         res |= ast_manager_unregister("ConfbridgeUnmute");
2667         res |= ast_manager_unregister("ConfbridgeKick");
2668         res |= ast_manager_unregister("ConfbridgeUnlock");
2669         res |= ast_manager_unregister("ConfbridgeLock");
2670         res |= ast_manager_unregister("ConfbridgeStartRecord");
2671         res |= ast_manager_unregister("ConfbridgeStopRecord");
2672
2673         return res;
2674 }
2675
2676 /*! \brief Called when module is being loaded */
2677 static int load_module(void)
2678 {
2679         int res = 0;
2680         if ((ast_custom_function_register(&confbridge_function))) {
2681                 return AST_MODULE_LOAD_FAILURE;
2682         }
2683         if ((ast_custom_function_register(&confbridge_info_function))) {
2684                 return AST_MODULE_LOAD_FAILURE;
2685         }
2686         if (!(record_tech.capabilities = ast_format_cap_alloc())) {
2687                 return AST_MODULE_LOAD_FAILURE;
2688         }
2689         ast_format_cap_add_all(record_tech.capabilities);
2690         if (ast_channel_register(&record_tech)) {
2691                 ast_log(LOG_ERROR, "Unable to register ConfBridge recorder.\n");
2692                 return AST_MODULE_LOAD_FAILURE;
2693         }
2694         /* Create a container to hold the conference bridges */
2695         if (!(conference_bridges = ao2_container_alloc(CONFERENCE_BRIDGE_BUCKETS, conference_bridge_hash_cb, conference_bridge_cmp_cb))) {
2696                 return AST_MODULE_LOAD_FAILURE;
2697         }
2698         if (ast_register_application_xml(app, confbridge_exec)) {
2699                 ao2_ref(conference_bridges, -1);
2700                 return AST_MODULE_LOAD_FAILURE;
2701         }
2702
2703         res |= ast_cli_register_multiple(cli_confbridge, sizeof(cli_confbridge) / sizeof(struct ast_cli_entry));
2704         res |= ast_manager_register_xml("ConfbridgeList", EVENT_FLAG_REPORTING, action_confbridgelist);
2705         res |= ast_manager_register_xml("ConfbridgeListRooms", EVENT_FLAG_REPORTING, action_confbridgelistrooms);
2706         res |= ast_manager_register_xml("ConfbridgeMute", EVENT_FLAG_CALL, action_confbridgemute);
2707         res |= ast_manager_register_xml("ConfbridgeUnmute", EVENT_FLAG_CALL, action_confbridgeunmute);
2708         res |= ast_manager_register_xml("ConfbridgeKick", EVENT_FLAG_CALL, action_confbridgekick);
2709         res |= ast_manager_register_xml("ConfbridgeUnlock", EVENT_FLAG_CALL, action_confbridgeunlock);
2710         res |= ast_manager_register_xml("ConfbridgeLock", EVENT_FLAG_CALL, action_confbridgelock);
2711         res |= ast_manager_register_xml("ConfbridgeStartRecord", EVENT_FLAG_CALL, action_confbridgestartrecord);
2712         res |= ast_manager_register_xml("ConfbridgeStopRecord", EVENT_FLAG_CALL, action_confbridgestoprecord);
2713         res |= ast_manager_register_xml("ConfbridgeSetSingleVideoSrc", EVENT_FLAG_CALL, action_confbridgesetsinglevideosrc);
2714
2715         conf_load_config(0);
2716         return res;
2717 }
2718
2719 static int reload(void)
2720 {
2721         return conf_load_config(1);
2722 }
2723
2724 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Conference Bridge Application",
2725         .load = load_module,
2726         .unload = unload_module,
2727         .reload = reload,
2728         .load_pri = AST_MODPRI_DEVSTATE_PROVIDER,
2729 );