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