Fix several XML documentation validate errors.
[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  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \brief Conference Bridge application
22  *
23  * \author\verbatim Joshua Colp <jcolp@digium.com> \endverbatim
24  *
25  * This is a conference bridge application utilizing the bridging core.
26  * \ingroup applications
27  */
28
29 #include "asterisk.h"
30
31 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <unistd.h>
36 #include <string.h>
37 #include <signal.h>
38
39 #include "asterisk/file.h"
40 #include "asterisk/logger.h"
41 #include "asterisk/channel.h"
42 #include "asterisk/pbx.h"
43 #include "asterisk/module.h"
44 #include "asterisk/lock.h"
45 #include "asterisk/app.h"
46 #include "asterisk/bridging.h"
47 #include "asterisk/musiconhold.h"
48 #include "asterisk/say.h"
49 #include "asterisk/audiohook.h"
50 #include "asterisk/astobj2.h"
51
52 /*** DOCUMENTATION
53         <application name="ConfBridge" language="en_US">
54                 <synopsis>
55                         Conference bridge application.
56                 </synopsis>
57                 <syntax>
58                         <parameter name="confno">
59                                 <para>The conference number</para>
60                         </parameter>
61                         <parameter name="options">
62                                 <optionlist>
63                                         <option name="a">
64                                                 <para>Set admin mode.</para>
65                                         </option>
66                                         <option name="A">
67                                                 <para>Set marked mode.</para>
68                                         </option>
69                                         <option name="c">
70                                                 <para>Announce user(s) count on joining a conference.</para>
71                                         </option>
72                                         <option name="m">
73                                                 <para>Set initially muted.</para>
74                                         </option>
75                                         <option name="M" hasparams="optional">
76                                                 <para>Enable music on hold when the conference has a single caller. Optionally,
77                                                 specify a musiconhold class to use. If one is not provided, it will use the
78                                                 channel's currently set music class, or <literal>default</literal>.</para>
79                                                 <argument name="class" required="true" />
80                                         </option>
81                                         <option name="1">
82                                                 <para>Do not play message when first person enters</para>
83                                         </option>
84                                         <option name="s">
85                                                 <para>Present menu (user or admin) when <literal>*</literal> is received
86                                                 (send to menu).</para>
87                                         </option>
88                                         <option name="w">
89                                                 <para>Wait until the marked user enters the conference.</para>
90                                         </option>
91                                         <option name="q">
92                                                 <para>Quiet mode (don't play enter/leave sounds).</para>
93                                         </option>
94                                 </optionlist>
95                       </parameter>
96                 </syntax>
97                 <description>
98                         <para>Enters the user into a specified conference bridge. The user can exit the conference by hangup only.</para>
99                         <para>The join sound can be set using the <literal>CONFBRIDGE_JOIN_SOUND</literal> variable and the leave sound can be set using the <literal>CONFBRIDGE_LEAVE_SOUND</literal> variable. These can be unique to the caller.</para>
100                         <note><para>This application will not automatically answer the channel.</para></note>
101                 </description>
102         </application>
103 ***/
104
105 /*!
106  * \par Playing back a file to a channel in a conference
107  * You might notice in this application that while playing a sound file
108  * to a channel the actual conference bridge lock is not held. This is done so
109  * that other channels are not blocked from interacting with the conference bridge.
110  * Unfortunately because of this it is possible for things to change after the sound file
111  * is done being played. Data must therefore be checked after reacquiring the conference
112  * bridge lock if it is important.
113  */
114
115 static const char app[] = "ConfBridge";
116
117 enum {
118         OPTION_ADMIN = (1 << 0),             /*!< Set if the caller is an administrator */
119         OPTION_MENU = (1 << 1),              /*!< Set if the caller should have access to the conference bridge IVR menu */
120         OPTION_MUSICONHOLD = (1 << 2),       /*!< Set if music on hold should be played if nobody else is in the conference bridge */
121         OPTION_NOONLYPERSON = (1 << 3),      /*!< Set if the "you are currently the only person in this conference" sound file should not be played */
122         OPTION_STARTMUTED = (1 << 4),        /*!< Set if the caller should be initially set muted */
123         OPTION_ANNOUNCEUSERCOUNT = (1 << 5), /*!< Set if the number of users should be announced to the caller */
124         OPTION_MARKEDUSER = (1 << 6),        /*!< Set if the caller is a marked user */
125         OPTION_WAITMARKED = (1 << 7),        /*!< Set if the conference must wait for a marked user before starting */
126         OPTION_QUIET = (1 << 8),             /*!< Set if no audio prompts should be played */
127 };
128
129 enum {
130         OPTION_MUSICONHOLD_CLASS,            /*!< If the 'M' option is set, the music on hold class to play */
131         /*This must be the last element */
132         OPTION_ARRAY_SIZE,
133 };
134
135 AST_APP_OPTIONS(app_opts,{
136         AST_APP_OPTION('A', OPTION_MARKEDUSER),
137         AST_APP_OPTION('a', OPTION_ADMIN),
138         AST_APP_OPTION('c', OPTION_ANNOUNCEUSERCOUNT),
139         AST_APP_OPTION('m', OPTION_STARTMUTED),
140         AST_APP_OPTION_ARG('M', OPTION_MUSICONHOLD, OPTION_MUSICONHOLD_CLASS),
141         AST_APP_OPTION('1', OPTION_NOONLYPERSON),
142         AST_APP_OPTION('s', OPTION_MENU),
143         AST_APP_OPTION('w', OPTION_WAITMARKED),
144         AST_APP_OPTION('q', OPTION_QUIET),
145 });
146
147 /* Maximum length of a conference bridge name */
148 #define MAX_CONF_NAME 32
149
150 /* Number of buckets our conference bridges container can have */
151 #define CONFERENCE_BRIDGE_BUCKETS 53
152
153 /*! \brief The structure that represents a conference bridge */
154 struct conference_bridge {
155         char name[MAX_CONF_NAME];                                         /*!< Name of the conference bridge */
156         struct ast_bridge *bridge;                                        /*!< Bridge structure doing the mixing */
157         unsigned int users;                                               /*!< Number of users present */
158         unsigned int markedusers;                                         /*!< Number of marked users present */
159         unsigned int locked:1;                                            /*!< Is this conference bridge locked? */
160         AST_LIST_HEAD_NOLOCK(, conference_bridge_user) users_list;        /*!< List of users participating in the conference bridge */
161         struct ast_channel *playback_chan;                                /*!< Channel used for playback into the conference bridge */
162         ast_mutex_t playback_lock;                                        /*!< Lock used for playback channel */
163 };
164
165 /*! \brief The structure that represents a conference bridge user */
166 struct conference_bridge_user {
167         struct conference_bridge *conference_bridge; /*!< Conference bridge they are participating in */
168         struct ast_channel *chan;                    /*!< Asterisk channel participating */
169         struct ast_flags flags;                      /*!< Flags passed in when the application was called */
170         char *opt_args[OPTION_ARRAY_SIZE];           /*!< Arguments to options passed when application was called */
171         struct ast_bridge_features features;         /*!< Bridge features structure */
172         unsigned int kicked:1;                       /*!< User has been kicked from the conference */
173         AST_LIST_ENTRY(conference_bridge_user) list; /*!< Linked list information */
174 };
175
176 /*! \brief Container to hold all conference bridges in progress */
177 static struct ao2_container *conference_bridges;
178
179 static int play_sound_file(struct conference_bridge *conference_bridge, const char *filename);
180
181 /*! \brief Hashing function used for conference bridges container */
182 static int conference_bridge_hash_cb(const void *obj, const int flags)
183 {
184         const struct conference_bridge *conference_bridge = obj;
185         return ast_str_case_hash(conference_bridge->name);
186 }
187
188 /*! \brief Comparison function used for conference bridges container */
189 static int conference_bridge_cmp_cb(void *obj, void *arg, int flags)
190 {
191         const struct conference_bridge *conference_bridge0 = obj, *conference_bridge1 = arg;
192         return (!strcasecmp(conference_bridge0->name, conference_bridge1->name) ? CMP_MATCH | CMP_STOP : 0);
193 }
194
195 /*!
196  * \brief Announce number of users in the conference bridge to the caller
197  *
198  * \param conference_bridge Conference bridge to peek at
199  * \param conference_bridge_user Caller
200  *
201  * \return Returns nothing
202  */
203 static void announce_user_count(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user)
204 {
205         if (conference_bridge->users == 1) {
206                 /* Awww we are the only person in the conference bridge */
207                 return;
208         } else if (conference_bridge->users == 2) {
209                 /* Eep, there is one other person */
210                 if (ast_stream_and_wait(conference_bridge_user->chan, "conf-onlyone", "")) {
211                         return;
212                 }
213         } else {
214                 /* Alas multiple others in here */
215                 if (ast_stream_and_wait(conference_bridge_user->chan, "conf-thereare", "")) {
216                         return;
217                 }
218                 if (ast_say_number(conference_bridge_user->chan, conference_bridge->users - 1, "", conference_bridge_user->chan->language, NULL)) {
219                         return;
220                 }
221                 if (ast_stream_and_wait(conference_bridge_user->chan, "conf-otherinparty", "")) {
222                         return;
223                 }
224         }
225 }
226
227 /*!
228  * \brief Play back an audio file to a channel
229  *
230  * \param conference_bridge Conference bridge they are in
231  * \param chan Channel to play audio prompt to
232  * \param file Prompt to play
233  *
234  * \return Returns nothing
235  *
236  * \note This function assumes that conference_bridge is locked
237  */
238 static void play_prompt_to_channel(struct conference_bridge *conference_bridge, struct ast_channel *chan, const char *file)
239 {
240         ao2_unlock(conference_bridge);
241         ast_stream_and_wait(chan, file, "");
242         ao2_lock(conference_bridge);
243 }
244
245 /*!
246  * \brief Perform post-joining marked specific actions
247  *
248  * \param conference_bridge Conference bridge being joined
249  * \param conference_bridge_user Conference bridge user joining
250  *
251  * \return Returns nothing
252  */
253 static void post_join_marked(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user)
254 {
255         if (ast_test_flag(&conference_bridge_user->flags, OPTION_MARKEDUSER)) {
256                 struct conference_bridge_user *other_conference_bridge_user = NULL;
257
258                 /* If we are not the first marked user to join just bail out now */
259                 if (conference_bridge->markedusers >= 2) {
260                         return;
261                 }
262
263                 /* Iterate through every participant stopping MOH on them if need be */
264                 AST_LIST_TRAVERSE(&conference_bridge->users_list, other_conference_bridge_user, list) {
265                         if (other_conference_bridge_user == conference_bridge_user) {
266                                 continue;
267                         }
268                         if (ast_test_flag(&other_conference_bridge_user->flags, OPTION_MUSICONHOLD) && !ast_bridge_suspend(conference_bridge->bridge, other_conference_bridge_user->chan)) {
269                                 ast_moh_stop(other_conference_bridge_user->chan);
270                                 ast_bridge_unsuspend(conference_bridge->bridge, other_conference_bridge_user->chan);
271                         }
272                 }
273
274                 /* Next play the audio file stating they are going to be placed into the conference */
275                 if (!ast_test_flag(&conference_bridge_user->flags, OPTION_QUIET)) {
276                         ao2_unlock(conference_bridge);
277                         ast_autoservice_start(conference_bridge_user->chan);
278                         play_sound_file(conference_bridge, "conf-placeintoconf");
279                         ast_autoservice_stop(conference_bridge_user->chan);
280                         ao2_lock(conference_bridge);
281                 }
282
283                 /* Finally iterate through and unmute them all */
284                 AST_LIST_TRAVERSE(&conference_bridge->users_list, other_conference_bridge_user, list) {
285                         if (other_conference_bridge_user == conference_bridge_user) {
286                                 continue;
287                         }
288                         other_conference_bridge_user->features.mute = 0;
289                 }
290
291         } else {
292                 /* If a marked user already exists in the conference bridge we can just bail out now */
293                 if (conference_bridge->markedusers) {
294                         return;
295                 }
296                 /* Be sure we are muted so we can't talk to anybody else waiting */
297                 conference_bridge_user->features.mute = 1;
298                 /* If we have not been quieted play back that they are waiting for the leader */
299                 if (!ast_test_flag(&conference_bridge_user->flags, OPTION_QUIET)) {
300                         play_prompt_to_channel(conference_bridge, conference_bridge_user->chan, "conf-waitforleader");
301                 }
302                 /* Start music on hold if needed */
303                 /* We need to recheck the markedusers value here. play_prompt_to_channel unlocks the conference bridge, potentially
304                  * allowing a marked user to enter while the prompt was playing
305                  */
306                 if (!conference_bridge->markedusers && ast_test_flag(&conference_bridge_user->flags, OPTION_MUSICONHOLD)) {
307                         ast_moh_start(conference_bridge_user->chan, conference_bridge_user->opt_args[OPTION_MUSICONHOLD_CLASS], NULL);
308                 }
309         }
310 }
311
312 /*!
313  * \brief Perform post-joining non-marked specific actions
314  *
315  * \param conference_bridge Conference bridge being joined
316  * \param conference_bridge_user Conference bridge user joining
317  *
318  * \return Returns nothing
319  */
320 static void post_join_unmarked(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user)
321 {
322         /* Play back audio prompt and start MOH if need be if we are the first participant */
323         if (conference_bridge->users == 1) {
324                 /* If audio prompts have not been quieted or this prompt quieted play it on out */
325                 if (!ast_test_flag(&conference_bridge_user->flags, OPTION_QUIET | OPTION_NOONLYPERSON)) {
326                         play_prompt_to_channel(conference_bridge, conference_bridge_user->chan, "conf-onlyperson");
327                 }
328                 /* If we need to start music on hold on the channel do so now */
329                 /* We need to re-check the number of users in the conference bridge here because another conference bridge
330                  * participant could have joined while the above prompt was playing for the first user.
331                  */
332                 if (conference_bridge->users == 1 && ast_test_flag(&conference_bridge_user->flags, OPTION_MUSICONHOLD)) {
333                         ast_moh_start(conference_bridge_user->chan, conference_bridge_user->opt_args[OPTION_MUSICONHOLD_CLASS], NULL);
334                 }
335                 return;
336         }
337
338         /* Announce number of users if need be */
339         if (ast_test_flag(&conference_bridge_user->flags, OPTION_ANNOUNCEUSERCOUNT)) {
340                 ao2_unlock(conference_bridge);
341                 announce_user_count(conference_bridge, conference_bridge_user);
342                 ao2_lock(conference_bridge);
343         }
344
345         /* If we are the second participant we may need to stop music on hold on the first */
346         if (conference_bridge->users == 2) {
347                 struct conference_bridge_user *first_participant = AST_LIST_FIRST(&conference_bridge->users_list);
348
349                 /* Temporarily suspend the above participant from the bridge so we have control to stop MOH if needed */
350                 if (ast_test_flag(&first_participant->flags, OPTION_MUSICONHOLD) && !ast_bridge_suspend(conference_bridge->bridge, first_participant->chan)) {
351                         ast_moh_stop(first_participant->chan);
352                         ast_bridge_unsuspend(conference_bridge->bridge, first_participant->chan);
353                 }
354         }
355 }
356
357 /*!
358  * \brief Destroy a conference bridge
359  *
360  * \param obj The conference bridge object
361  *
362  * \return Returns nothing
363  */
364 static void destroy_conference_bridge(void *obj)
365 {
366         struct conference_bridge *conference_bridge = obj;
367
368         ast_debug(1, "Destroying conference bridge '%s'\n", conference_bridge->name);
369
370         ast_mutex_destroy(&conference_bridge->playback_lock);
371
372         if (conference_bridge->playback_chan) {
373                 struct ast_channel *underlying_channel = conference_bridge->playback_chan->tech->bridged_channel(conference_bridge->playback_chan, NULL);
374                 ast_hangup(underlying_channel);
375                 ast_hangup(conference_bridge->playback_chan);
376                 conference_bridge->playback_chan = NULL;
377         }
378
379         /* Destroying a conference bridge is simple, all we have to do is destroy the bridging object */
380         if (conference_bridge->bridge) {
381                 ast_bridge_destroy(conference_bridge->bridge);
382                 conference_bridge->bridge = NULL;
383         }
384 }
385
386 /*!
387  * \brief Join a conference bridge
388  *
389  * \param name The conference name
390  * \param conference_bridge_user Conference bridge user structure
391  *
392  * \return A pointer to the conference bridge struct, or NULL if the conference room wasn't found.
393  */
394 static struct conference_bridge *join_conference_bridge(const char *name, struct conference_bridge_user *conference_bridge_user)
395 {
396         struct conference_bridge *conference_bridge = NULL;
397         struct conference_bridge tmp;
398
399         ast_copy_string(tmp.name, name, sizeof(tmp.name));
400
401         /* We explictly lock the conference bridges container ourselves so that other callers can not create duplicate conferences at the same */
402         ao2_lock(conference_bridges);
403
404         ast_debug(1, "Trying to find conference bridge '%s'\n", name);
405
406         /* Attempt to find an existing conference bridge */
407         conference_bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
408
409         /* When finding a conference bridge that already exists make sure that it is not locked, and if so that we are not an admin */
410         if (conference_bridge && conference_bridge->locked && !ast_test_flag(&conference_bridge_user->flags, OPTION_ADMIN)) {
411                 ao2_unlock(conference_bridges);
412                 ao2_ref(conference_bridge, -1);
413                 ast_debug(1, "Conference bridge '%s' is locked and caller is not an admin\n", name);
414                 ast_stream_and_wait(conference_bridge_user->chan, "conf-locked", "");
415                 return NULL;
416         }
417
418         /* If no conference bridge was found see if we can create one */
419         if (!conference_bridge) {
420                 /* Try to allocate memory for a new conference bridge, if we fail... this won't end well. */
421                 if (!(conference_bridge = ao2_alloc(sizeof(*conference_bridge), destroy_conference_bridge))) {
422                         ao2_unlock(conference_bridges);
423                         ast_log(LOG_ERROR, "Conference bridge '%s' does not exist.\n", name);
424                         return NULL;
425                 }
426
427                 /* Setup conference bridge parameters */
428                 ast_copy_string(conference_bridge->name, name, sizeof(conference_bridge->name));
429
430                 /* Create an actual bridge that will do the audio mixing */
431                 if (!(conference_bridge->bridge = ast_bridge_new(AST_BRIDGE_CAPABILITY_1TO1MIX, AST_BRIDGE_FLAG_SMART))) {
432                         ao2_ref(conference_bridge, -1);
433                         conference_bridge = NULL;
434                         ao2_unlock(conference_bridges);
435                         ast_log(LOG_ERROR, "Conference bridge '%s' could not be created.\n", name);
436                         return NULL;
437                 }
438
439                 /* Setup lock for playback channel */
440                 ast_mutex_init(&conference_bridge->playback_lock);
441
442                 /* Link it into the conference bridges container */
443                 ao2_link(conference_bridges, conference_bridge);
444
445                 ast_debug(1, "Created conference bridge '%s' and linked to container '%p'\n", name, conference_bridges);
446         }
447
448         ao2_unlock(conference_bridges);
449
450         /* Setup conference bridge user parameters */
451         conference_bridge_user->conference_bridge = conference_bridge;
452
453         ao2_lock(conference_bridge);
454
455         /* All good to go, add them in */
456         AST_LIST_INSERT_TAIL(&conference_bridge->users_list, conference_bridge_user, list);
457
458         /* Increment the users count on the bridge, but record it as it is going to need to be known right after this */
459         conference_bridge->users++;
460
461         /* If the caller is a marked user bump up the count */
462         if (ast_test_flag(&conference_bridge_user->flags, OPTION_MARKEDUSER)) {
463                 conference_bridge->markedusers++;
464         }
465
466         /* 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 */
467         if (ast_test_flag(&conference_bridge_user->flags, OPTION_MARKEDUSER | OPTION_WAITMARKED)) {
468                 post_join_marked(conference_bridge, conference_bridge_user);
469         } else {
470                 post_join_unmarked(conference_bridge, conference_bridge_user);
471         }
472
473         ao2_unlock(conference_bridge);
474
475         return conference_bridge;
476 }
477
478 /*!
479  * \brief Leave a conference bridge
480  *
481  * \param conference_bridge The conference bridge to leave
482  * \param conference_bridge_user The conference bridge user structure
483  *
484  */
485 static void  leave_conference_bridge(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user)
486 {
487         ao2_lock(conference_bridge);
488
489         /* If this caller is a marked user bump down the count */
490         if (ast_test_flag(&conference_bridge_user->flags, OPTION_MARKEDUSER)) {
491                 conference_bridge->markedusers--;
492         }
493
494         /* Decrement the users count while keeping the previous participant count */
495         conference_bridge->users--;
496
497         /* Drop conference bridge user from the list, they be going bye bye */
498         AST_LIST_REMOVE(&conference_bridge->users_list, conference_bridge_user, list);
499
500         /* If there are still users in the conference bridge we may need to do things (such as start MOH on them) */
501         if (conference_bridge->users) {
502                 if (ast_test_flag(&conference_bridge_user->flags, OPTION_MARKEDUSER) && !conference_bridge->markedusers) {
503                         struct conference_bridge_user *other_participant = NULL;
504
505                         /* Start out with muting everyone */
506                         AST_LIST_TRAVERSE(&conference_bridge->users_list, other_participant, list) {
507                                 other_participant->features.mute = 1;
508                         }
509
510                         /* Play back the audio prompt saying the leader has left the conference */
511                         if (!ast_test_flag(&conference_bridge_user->flags, OPTION_QUIET)) {
512                                 ao2_unlock(conference_bridge);
513                                 ast_autoservice_start(conference_bridge_user->chan);
514                                 play_sound_file(conference_bridge, "conf-leaderhasleft");
515                                 ast_autoservice_stop(conference_bridge_user->chan);
516                                 ao2_lock(conference_bridge);
517                         }
518
519                         /* Now on to starting MOH if needed */
520                         AST_LIST_TRAVERSE(&conference_bridge->users_list, other_participant, list) {
521                                 if (ast_test_flag(&other_participant->flags, OPTION_MUSICONHOLD) && !ast_bridge_suspend(conference_bridge->bridge, other_participant->chan)) {
522                                         ast_moh_start(other_participant->chan, other_participant->opt_args[OPTION_MUSICONHOLD_CLASS], NULL);
523                                         ast_bridge_unsuspend(conference_bridge->bridge, other_participant->chan);
524                                 }
525                         }
526                 } else if (conference_bridge->users == 1) {
527                         /* Of course if there is one other person in here we may need to start up MOH on them */
528                         struct conference_bridge_user *first_participant = AST_LIST_FIRST(&conference_bridge->users_list);
529
530                         if (ast_test_flag(&first_participant->flags, OPTION_MUSICONHOLD) && !ast_bridge_suspend(conference_bridge->bridge, first_participant->chan)) {
531                                 ast_moh_start(first_participant->chan, first_participant->opt_args[OPTION_MUSICONHOLD_CLASS], NULL);
532                                 ast_bridge_unsuspend(conference_bridge->bridge, first_participant->chan);
533                         }
534                 }
535         } else {
536                 ao2_unlink(conference_bridges, conference_bridge);
537         }
538
539         /* Done mucking with the conference bridge, huzzah */
540         ao2_unlock(conference_bridge);
541
542         ao2_ref(conference_bridge, -1);
543 }
544
545 /*!
546  * \brief Play sound file into conference bridge
547  *
548  * \param conference_bridge The conference bridge to play sound file into
549  * \param filename Sound file to play
550  *
551  * \retval 0 success
552  * \retval -1 failure
553  */
554 static int play_sound_file(struct conference_bridge *conference_bridge, const char *filename)
555 {
556         struct ast_channel *underlying_channel;
557
558         ast_mutex_lock(&conference_bridge->playback_lock);
559
560         if (!(conference_bridge->playback_chan)) {
561                 int cause;
562
563                 if (!(conference_bridge->playback_chan = ast_request("Bridge", AST_FORMAT_SLINEAR, NULL, "", &cause))) {
564                         ast_mutex_unlock(&conference_bridge->playback_lock);
565                         return -1;
566                 }
567
568                 conference_bridge->playback_chan->bridge = conference_bridge->bridge;
569
570                 if (ast_call(conference_bridge->playback_chan, "", 0)) {
571                         ast_hangup(conference_bridge->playback_chan);
572                         conference_bridge->playback_chan = NULL;
573                         ast_mutex_unlock(&conference_bridge->playback_lock);
574                         return -1;
575                 }
576
577                 ast_debug(1, "Created a playback channel to conference bridge '%s'\n", conference_bridge->name);
578
579                 underlying_channel = conference_bridge->playback_chan->tech->bridged_channel(conference_bridge->playback_chan, NULL);
580         } else {
581                 /* Channel was already available so we just need to add it back into the bridge */
582                 underlying_channel = conference_bridge->playback_chan->tech->bridged_channel(conference_bridge->playback_chan, NULL);
583                 ast_bridge_impart(conference_bridge->bridge, underlying_channel, NULL, NULL);
584         }
585
586         /* The channel is all under our control, in goes the prompt */
587         ast_stream_and_wait(conference_bridge->playback_chan, filename, "");
588
589         ast_debug(1, "Departing underlying channel '%s' from bridge '%p'\n", underlying_channel->name, conference_bridge->bridge);
590         ast_bridge_depart(conference_bridge->bridge, underlying_channel);
591
592         ast_mutex_unlock(&conference_bridge->playback_lock);
593
594         return 0;
595 }
596
597 /*!
598  * \brief DTMF Menu Callback
599  *
600  * \param bridge Bridge this is involving
601  * \param bridge_channel Bridged channel this is involving
602  * \param hook_pvt User's conference bridge structure
603  *
604  * \retval 0 success
605  * \retval -1 failure
606  */
607 static int menu_callback(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
608 {
609         struct conference_bridge_user *conference_bridge_user = hook_pvt;
610         struct conference_bridge *conference_bridge = conference_bridge_user->conference_bridge;
611         int digit, res = 0, isadmin = ast_test_flag(&conference_bridge_user->flags, OPTION_ADMIN);
612
613         /* See if music on hold is playing */
614         ao2_lock(conference_bridge);
615         if (conference_bridge->users == 1 && ast_test_flag(&conference_bridge_user->flags, OPTION_MUSICONHOLD)) {
616                 /* Just us so MOH is probably indeed going, let's stop it */
617                 ast_moh_stop(bridge_channel->chan);
618         }
619         ao2_unlock(conference_bridge);
620
621         /* Try to play back the user menu, if it fails pass this back up so the bridging core will act on it */
622         if (ast_streamfile(bridge_channel->chan, (isadmin ? "conf-adminmenu" : "conf-usermenu"), bridge_channel->chan->language)) {
623                 res = -1;
624                 goto finished;
625         }
626
627         /* Wait for them to enter a digit from the user menu options */
628         digit = ast_waitstream(bridge_channel->chan, AST_DIGIT_ANY);
629         ast_stopstream(bridge_channel->chan);
630
631         if (digit == '1') {
632                 /* 1 - Mute or unmute yourself, note we only allow manipulation if they aren't waiting for a marked user or if marked users exist */
633                 if (!ast_test_flag(&conference_bridge_user->flags, OPTION_WAITMARKED) || conference_bridge->markedusers) {
634                         conference_bridge_user->features.mute = (!conference_bridge_user->features.mute ? 1 : 0);
635                 }
636                 res = ast_stream_and_wait(bridge_channel->chan, (conference_bridge_user->features.mute ? "conf-muted" : "conf-unmuted"), "");
637         } else if (isadmin && digit == '2') {
638                 /* 2 - Unlock or lock conference */
639                 conference_bridge->locked = (!conference_bridge->locked ? 1 : 0);
640                 res = ast_stream_and_wait(bridge_channel->chan, (conference_bridge->locked ? "conf-lockednow" : "conf-unlockednow"), "");
641         } else if (isadmin && digit == '3') {
642                 /* 3 - Eject last user */
643                 struct conference_bridge_user *last_participant = NULL;
644
645                 ao2_lock(conference_bridge);
646                 if (((last_participant = AST_LIST_LAST(&conference_bridge->users_list)) == conference_bridge_user) || (ast_test_flag(&last_participant->flags, OPTION_ADMIN))) {
647                         ao2_unlock(conference_bridge);
648                         res = ast_stream_and_wait(bridge_channel->chan, "conf-errormenu", "");
649                 } else {
650                         last_participant->kicked = 1;
651                         ast_bridge_remove(conference_bridge->bridge, last_participant->chan);
652                         ao2_unlock(conference_bridge);
653                 }
654         } else if (digit == '4') {
655                 /* 4 - Decrease listening volume */
656                 ast_audiohook_volume_adjust(conference_bridge_user->chan, AST_AUDIOHOOK_DIRECTION_WRITE, -1);
657         } else if (digit == '6') {
658                 /* 6 - Increase listening volume */
659                 ast_audiohook_volume_adjust(conference_bridge_user->chan, AST_AUDIOHOOK_DIRECTION_WRITE, 1);
660         } else if (digit == '7') {
661                 /* 7 - Decrease talking volume */
662                 ast_audiohook_volume_adjust(conference_bridge_user->chan, AST_AUDIOHOOK_DIRECTION_READ, -1);
663         } else if (digit == '8') {
664                 /* 8 - Exit the IVR */
665         } else if (digit == '9') {
666                 /* 9 - Increase talking volume */
667                 ast_audiohook_volume_adjust(conference_bridge_user->chan, AST_AUDIOHOOK_DIRECTION_READ, 1);
668         } else {
669                 /* No valid option was selected */
670                 res = ast_stream_and_wait(bridge_channel->chan, "conf-errormenu", "");
671         }
672
673  finished:
674         /* See if music on hold needs to be started back up again */
675         ao2_lock(conference_bridge);
676         if (conference_bridge->users == 1 && ast_test_flag(&conference_bridge_user->flags, OPTION_MUSICONHOLD)) {
677                 ast_moh_start(bridge_channel->chan, conference_bridge_user->opt_args[OPTION_MUSICONHOLD_CLASS], NULL);
678         }
679         ao2_unlock(conference_bridge);
680
681         bridge_channel->state = AST_BRIDGE_CHANNEL_STATE_WAIT;
682
683         return res;
684 }
685
686 /*! \brief The ConfBridge application */
687 static int confbridge_exec(struct ast_channel *chan, const char *data)
688 {
689         int res = 0, volume_adjustments[2];
690         char *parse;
691         struct conference_bridge *conference_bridge = NULL;
692         struct conference_bridge_user conference_bridge_user = {
693                 .chan = chan,
694         };
695         const char *tmp, *join_sound = NULL, *leave_sound = NULL;
696         AST_DECLARE_APP_ARGS(args,
697                 AST_APP_ARG(conf_name);
698                 AST_APP_ARG(options);
699         );
700
701         if (ast_strlen_zero(data)) {
702                 ast_log(LOG_WARNING, "%s requires an argument (conference name[,options])\n", app);
703                 return -1;
704         }
705
706         /* We need to make a copy of the input string if we are going to modify it! */
707         parse = ast_strdupa(data);
708
709         AST_STANDARD_APP_ARGS(args, parse);
710
711         if (args.argc == 2) {
712                 ast_app_parse_options(app_opts, &conference_bridge_user.flags, conference_bridge_user.opt_args, args.options);
713         }
714
715         /* Look for a conference bridge matching the provided name */
716         if (!(conference_bridge = join_conference_bridge(args.conf_name, &conference_bridge_user))) {
717                 return -1;
718         }
719
720         /* Keep a copy of volume adjustments so we can restore them later if need be */
721         volume_adjustments[0] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_READ);
722         volume_adjustments[1] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_WRITE);
723
724         /* Always initialize the features structure, we are in most cases always going to need it. */
725         ast_bridge_features_init(&conference_bridge_user.features);
726
727         /* If the menu option is enabled provide a user or admin menu as a custom feature hook */
728         if (ast_test_flag(&conference_bridge_user.flags, OPTION_MENU)) {
729                 ast_bridge_features_hook(&conference_bridge_user.features, "#", menu_callback, &conference_bridge_user);
730         }
731
732         /* If the caller should be joined already muted, make it so */
733         if (ast_test_flag(&conference_bridge_user.flags, OPTION_STARTMUTED)) {
734                 conference_bridge_user.features.mute = 1;
735         }
736
737         /* Grab join/leave sounds from the channel */
738         ast_channel_lock(chan);
739         if ((tmp = pbx_builtin_getvar_helper(chan, "CONFBRIDGE_JOIN_SOUND"))) {
740                 join_sound = ast_strdupa(tmp);
741         }
742         if ((tmp = pbx_builtin_getvar_helper(chan, "CONFBRIDGE_LEAVE_SOUND"))) {
743                 leave_sound = ast_strdupa(tmp);
744         }
745         ast_channel_unlock(chan);
746
747         /* If there is 1 or more people already in the conference then play our join sound unless overridden */
748         if (!ast_test_flag(&conference_bridge_user.flags, OPTION_QUIET) && !ast_strlen_zero(join_sound) && conference_bridge->users >= 2) {
749                 ast_autoservice_start(chan);
750                 play_sound_file(conference_bridge, join_sound);
751                 ast_autoservice_stop(chan);
752         }
753
754         /* Join our conference bridge for real */
755         ast_bridge_join(conference_bridge->bridge, chan, NULL, &conference_bridge_user.features);
756
757         /* If there is 1 or more people (not including us) already in the conference then play our leave sound unless overridden */
758         if (!ast_test_flag(&conference_bridge_user.flags, OPTION_QUIET) && !ast_strlen_zero(leave_sound) && conference_bridge->users >= 2) {
759                 ast_autoservice_start(chan);
760                 play_sound_file(conference_bridge, leave_sound);
761                 ast_autoservice_stop(chan);
762         }
763
764         /* Easy as pie, depart this channel from the conference bridge */
765         leave_conference_bridge(conference_bridge, &conference_bridge_user);
766         conference_bridge = NULL;
767
768         /* Can't forget to clean up the features structure, or else we risk a memory leak */
769         ast_bridge_features_cleanup(&conference_bridge_user.features);
770
771         /* If the user was kicked from the conference play back the audio prompt for it */
772         if (!ast_test_flag(&conference_bridge_user.flags, OPTION_QUIET) && conference_bridge_user.kicked) {
773                 res = ast_stream_and_wait(chan, "conf-kicked", "");
774         }
775
776         /* Restore volume adjustments to previous values in case they were changed */
777         if (volume_adjustments[0]) {
778                 ast_audiohook_volume_set(chan, AST_AUDIOHOOK_DIRECTION_READ, volume_adjustments[0]);
779         }
780         if (volume_adjustments[1]) {
781                 ast_audiohook_volume_set(chan, AST_AUDIOHOOK_DIRECTION_WRITE, volume_adjustments[1]);
782         }
783
784         return res;
785 }
786
787 /*! \brief Called when module is being unloaded */
788 static int unload_module(void)
789 {
790         int res = ast_unregister_application(app);
791
792         /* Get rid of the conference bridges container. Since we only allow dynamic ones none will be active. */
793         ao2_ref(conference_bridges, -1);
794
795         return res;
796 }
797
798 /*! \brief Called when module is being loaded */
799 static int load_module(void)
800 {
801         /* Create a container to hold the conference bridges */
802         if (!(conference_bridges = ao2_container_alloc(CONFERENCE_BRIDGE_BUCKETS, conference_bridge_hash_cb, conference_bridge_cmp_cb))) {
803                 return AST_MODULE_LOAD_DECLINE;
804         }
805
806         if (ast_register_application_xml(app, confbridge_exec)) {
807                 ao2_ref(conference_bridges, -1);
808                 return AST_MODULE_LOAD_DECLINE;
809         }
810
811         return AST_MODULE_LOAD_SUCCESS;
812 }
813
814 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Conference Bridge Application");