Binaural synthesis (confbridge): On/off setting for binaural synthesis.
[asterisk/asterisk.git] / apps / confbridge / conf_config_parser.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2011, Digium, Inc.
5  *
6  * David Vossel <dvossel@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 ConfBridge config parser
22  *
23  * \author David Vossel <dvossel@digium.com>
24  */
25
26 /*** MODULEINFO
27         <support_level>core</support_level>
28  ***/
29
30 #include "asterisk.h"
31
32 ASTERISK_REGISTER_FILE()
33 #include "asterisk/logger.h"
34 #include "asterisk/config.h"
35 #include "asterisk/config_options.h"
36 #include "include/confbridge.h"
37 #include "asterisk/astobj2.h"
38 #include "asterisk/cli.h"
39 #include "asterisk/bridge_features.h"
40 #include "asterisk/stringfields.h"
41 #include "asterisk/pbx.h"
42
43
44 /*** DOCUMENTATION
45         <configInfo name="app_confbridge" language="en_US">
46                 <synopsis>Conference Bridge Application</synopsis>
47                 <configFile name="confbridge.conf">
48                         <configObject name="global">
49                                 <synopsis>Unused, but reserved.</synopsis>
50                         </configObject>
51                         <configObject name="user_profile">
52                                 <synopsis>A named profile to apply to specific callers.</synopsis>
53                                 <description><para>Callers in a ConfBridge have a profile associated with them
54                                 that determine their options. A configuration section is determined to be a
55                                 user_profile when the <literal>type</literal> parameter has a value
56                                 of <literal>user</literal>.
57                                 </para></description>
58                                 <configOption name="type">
59                                         <synopsis>Define this configuration category as a user profile.</synopsis>
60                                         <description><para>The type parameter determines how a context in the
61                                         configuration file is interpreted.</para>
62                                         <enumlist>
63                                                 <enum name="user"><para>Configure the context as a <replaceable>user_profile</replaceable></para></enum>
64                                                 <enum name="bridge"><para>Configure the context as a <replaceable>bridge_profile</replaceable></para></enum>
65                                                 <enum name="menu"><para>Configure the context as a <replaceable>menu</replaceable></para></enum>
66                                         </enumlist>
67                                         </description>
68                                 </configOption>
69                                 <configOption name="admin">
70                                         <synopsis>Sets if the user is an admin or not</synopsis>
71                                 </configOption>
72                                 <configOption name="marked">
73                                         <synopsis>Sets if this is a marked user or not</synopsis>
74                                 </configOption>
75                                 <configOption name="startmuted">
76                                         <synopsis>Sets if all users should start out muted</synopsis>
77                                 </configOption>
78                                 <configOption name="music_on_hold_when_empty">
79                                         <synopsis>Play MOH when user is alone or waiting on a marked user</synopsis>
80                                 </configOption>
81                                 <configOption name="quiet">
82                                         <synopsis>Silence enter/leave prompts and user intros for this user</synopsis>
83                                 </configOption>
84                                 <configOption name="announce_user_count">
85                                         <synopsis>Sets if the number of users should be announced to the user</synopsis>
86                                 </configOption>
87                                 <configOption name="announce_user_count_all">
88                                         <synopsis>Announce user count to all the other users when this user joins</synopsis>
89                                         <description><para>Sets if the number of users should be announced to all the other users
90                                         in the conference when this user joins. This option can be either set to 'yes' or
91                                         a number. When set to a number, the announcement will only occur once the user
92                                         count is above the specified number.
93                                         </para></description>
94                                 </configOption>
95                                 <configOption name="announce_only_user">
96                                         <synopsis>Announce to a user when they join an empty conference</synopsis>
97                                 </configOption>
98                                 <configOption name="wait_marked">
99                                         <synopsis>Sets if the user must wait for a marked user to enter before joining a conference</synopsis>
100                                 </configOption>
101                                 <configOption name="end_marked">
102                                         <synopsis>Kick the user from the conference when the last marked user leaves</synopsis>
103                                 </configOption>
104                                 <configOption name="talk_detection_events">
105                                         <synopsis>Set whether or not notifications of when a user begins and ends talking should be sent out as events over AMI</synopsis>
106                                 </configOption>
107                                 <configOption name="dtmf_passthrough">
108                                         <synopsis>Sets whether or not DTMF should pass through the conference</synopsis>
109                                 </configOption>
110                                 <configOption name="announce_join_leave">
111                                         <synopsis>Prompt user for their name when joining a conference and play it to the conference when they enter</synopsis>
112                                 </configOption>
113                                 <configOption name="announce_join_leave_review">
114                                         <synopsis>Prompt user for their name when joining a conference and play it to the conference when they enter.
115                                         The user will be asked to review the recording of their name before entering the conference.</synopsis>
116                                 </configOption>
117                                 <configOption name="pin">
118                                         <synopsis>Sets a PIN the user must enter before joining the conference</synopsis>
119                                 </configOption>
120                                 <configOption name="music_on_hold_class">
121                                         <synopsis>The MOH class to use for this user</synopsis>
122                                 </configOption>
123                                 <configOption name="announcement">
124                                         <synopsis>Sound file to play to the user when they join a conference</synopsis>
125                                 </configOption>
126                                 <configOption name="denoise">
127                                         <synopsis>Apply a denoise filter to the audio before mixing</synopsis>
128                                         <description><para>Sets whether or not a denoise filter should be applied
129                                         to the audio before mixing or not.  Off by default. Requires
130                                         <literal>codec_speex</literal> to be built and installed.  Do not confuse this option
131                                         with <replaceable>drop_silence</replaceable>.  Denoise is useful if there is a lot of background
132                                         noise for a user as it attempts to remove the noise while preserving
133                                         the speech.  This option does NOT remove silence from being mixed into
134                                         the conference and does come at the cost of a slight performance hit.
135                                         </para></description>
136                                 </configOption>
137                                 <configOption name="dsp_drop_silence">
138                                         <synopsis>Drop what Asterisk detects as silence from audio sent to the bridge</synopsis>
139                                         <description><para>
140                                         This option drops what Asterisk detects as silence from
141                                         entering into the bridge.  Enabling this option will drastically
142                                         improve performance and help remove the buildup of background
143                                         noise from the conference. Highly recommended for large conferences
144                                         due to its performance enhancements.
145                                         </para></description>
146                                 </configOption>
147                                 <configOption name="dsp_silence_threshold">
148                                         <synopsis>The number of milliseconds of detected silence necessary to trigger silence detection</synopsis>
149                                         <description><para>
150                                         The time in milliseconds of sound falling within the what
151                                         the dsp has established as baseline silence before a user
152                                         is considered be silent.  This value affects several
153                                         operations and should not be changed unless the impact
154                                         on call quality is fully understood.</para>
155                                         <para>What this value affects internally:</para>
156                                         <para>
157                                                 1. When talk detection AMI events are enabled, this value
158                                                 determines when the user has stopped talking after a
159                                                 period of talking.  If this value is set too low
160                                                 AMI events indicating the user has stopped talking
161                                                 may get falsely sent out when the user briefly pauses
162                                                 during mid sentence.
163                                         </para>
164                                         <para>
165                                                 2. The <replaceable>drop_silence</replaceable> option depends on this value to
166                                                 determine when the user's audio should begin to be
167                                                 dropped from the conference bridge after the user
168                                                 stops talking.  If this value is set too low the user's
169                                                 audio stream may sound choppy to the other participants.
170                                                 This is caused by the user transitioning constantly from
171                                                 silence to talking during mid sentence.
172                                         </para>
173                                         <para>
174                                                 The best way to approach this option is to set it slightly above
175                                                 the maximum amount of ms of silence a user may generate during
176                                                 natural speech.
177                                         </para>
178                                         <para>By default this value is 2500ms. Valid values are 1 through 2^31.</para>
179                                         </description>
180                                 </configOption>
181                                 <configOption name="dsp_talking_threshold">
182                                         <synopsis>The number of milliseconds of detected non-silence necessary to triger talk detection</synopsis>
183                                         <description><para>
184                                                 The time in milliseconds of sound above what the dsp has
185                                                 established as base line silence for a user before a user
186                                                 is considered to be talking.  This value affects several
187                                                 operations and should not be changed unless the impact on
188                                                 call quality is fully understood.</para>
189                                                 <para>
190                                                 What this value affects internally:
191                                                 </para>
192                                                 <para>
193                                                 1. Audio is only mixed out of a user's incoming audio stream
194                                                 if talking is detected.  If this value is set too
195                                                 loose the user will hear themselves briefly each
196                                                 time they begin talking until the dsp has time to
197                                                 establish that they are in fact talking.
198                                                 </para>
199                                                 <para>
200                                                 2. When talk detection AMI events are enabled, this value
201                                                 determines when talking has begun which results in
202                                                 an AMI event to fire.  If this value is set too tight
203                                                 AMI events may be falsely triggered by variants in
204                                                 room noise.
205                                                 </para>
206                                                 <para>
207                                                 3. The <replaceable>drop_silence</replaceable> option depends on this value to determine
208                                                 when the user's audio should be mixed into the bridge
209                                                 after periods of silence.  If this value is too loose
210                                                 the beginning of a user's speech will get cut off as they
211                                                 transition from silence to talking.
212                                                 </para>
213                                                 <para>By default this value is 160 ms. Valid values are 1 through 2^31</para>
214                                         </description>
215                                 </configOption>
216                                 <configOption name="jitterbuffer">
217                                         <synopsis>Place a jitter buffer on the user's audio stream before audio mixing is performed</synopsis>
218                                         <description><para>
219                                                 Enabling this option places a jitterbuffer on the user's audio stream
220                                                 before audio mixing is performed.  This is highly recommended but will
221                                                 add a slight delay to the audio.  This option is using the <literal>JITTERBUFFER</literal>
222                                                 dialplan function's default adaptive jitterbuffer.  For a more fine tuned
223                                                 jitterbuffer, disable this option and use the <literal>JITTERBUFFER</literal> dialplan function
224                                                 on the user before entering the ConfBridge application.
225                                         </para></description>
226                                 </configOption>
227                                 <configOption name="template">
228                                         <synopsis>When using the CONFBRIDGE dialplan function, use a user profile as a template for creating a new temporary profile</synopsis>
229                                 </configOption>
230                                 <configOption name="timeout">
231                                         <synopsis>Kick the user out of the conference after this many seconds. 0 means there is no timeout for the user.</synopsis>
232                                 </configOption>
233                         </configObject>
234                         <configObject name="bridge_profile">
235                                 <synopsis>A named profile to apply to specific bridges.</synopsis>
236                                 <description><para>ConfBridge bridges have a profile associated with them
237                                 that determine their options. A configuration section is determined to be a
238                                 <literal>bridge_profile</literal> when the <literal>type</literal> parameter has a value
239                                 of <literal>bridge</literal>.
240                                 </para></description>
241                                 <configOption name="type">
242                                         <synopsis>Define this configuration category as a bridge profile</synopsis>
243                                         <description><para>The type parameter determines how a context in the
244                                         configuration file is interpreted.</para>
245                                         <enumlist>
246                                                 <enum name="user"><para>Configure the context as a <replaceable>user_profile</replaceable></para></enum>
247                                                 <enum name="bridge"><para>Configure the context as a <replaceable>bridge_profile</replaceable></para></enum>
248                                                 <enum name="menu"><para>Configure the context as a <replaceable>menu</replaceable></para></enum>
249                                         </enumlist>
250                                         </description>
251                                 </configOption>
252                                 <configOption name="jitterbuffer">
253                                         <synopsis>Place a jitter buffer on the conference's audio stream</synopsis>
254                                 </configOption>
255                                 <configOption name="internal_sample_rate">
256                                         <synopsis>Set the internal native sample rate for mixing the conference</synopsis>
257                                         <description><para>
258                                                 Sets the internal native sample rate the
259                                                 conference is mixed at.  This is set to automatically
260                                                 adjust the sample rate to the best quality by default.
261                                                 Other values can be anything from 8000-192000.  If a
262                                                 sample rate is set that Asterisk does not support, the
263                                                 closest sample rate Asterisk does support to the one requested
264                                                 will be used.
265                                         </para></description>
266                                 </configOption>
267                                 <configOption name="language" default="en">
268                                         <synopsis>The language used for announcements to the conference.</synopsis>
269                                         <description><para>
270                                                 By default, announcements to a conference use English.  Which means
271                                                 the prompts played to all users within the conference will be
272                                                 English.  By changing the language of a bridge, this will change
273                                                 the language of the prompts played to all users.
274                                         </para></description>
275                                 </configOption>
276                                 <configOption name="mixing_interval">
277                                         <synopsis>Sets the internal mixing interval in milliseconds for the bridge</synopsis>
278                                         <description><para>
279                                                 Sets the internal mixing interval in milliseconds for the bridge.  This
280                                                 number reflects how tight or loose the mixing will be for the conference.
281                                                 In order to improve performance a larger mixing interval such as 40ms may
282                                                 be chosen.  Using a larger mixing interval comes at the cost of introducing
283                                                 larger amounts of delay into the bridge.  Valid values here are 10, 20, 40,
284                                                 or 80.
285                                         </para></description>
286                                 </configOption>
287                                 <configOption name="binaural_active">
288                                         <synopsis>If true binaural conferencing with stereo audio is active</synopsis>
289                                         <description><para>
290                                                 Activates binaural mixing for a conference bridge.
291                                                 Binaural features are disabled by default.
292                                         </para></description>
293                                 </configOption>
294                                 <configOption name="record_conference">
295                                         <synopsis>Record the conference starting with the first active user's entrance and ending with the last active user's exit</synopsis>
296                                         <description><para>
297                                                 Records the conference call starting when the first user
298                                                 enters the room, and ending when the last user exits the room.
299                                                 The default recorded filename is
300                                                 <filename>'confbridge-${name of conference bridge}-${start time}.wav'</filename>
301                                                 and the default format is 8khz slinear.  This file will be
302                                                 located in the configured monitoring directory in <filename>asterisk.conf</filename>.
303                                         </para></description>
304                                 </configOption>
305                                 <configOption name="record_file" default="confbridge-${name of conference bridge}-${start time}.wav">
306                                         <synopsis>The filename of the conference recording</synopsis>
307                                         <description><para>
308                                                 When <replaceable>record_conference</replaceable> is set to yes, the specific name of the
309                                                 record file can be set using this option.  Note that since multiple
310                                                 conferences may use the same bridge profile, this may cause issues
311                                                 depending on the configuration.  It is recommended to only use this
312                                                 option dynamically with the <literal>CONFBRIDGE()</literal> dialplan function. This
313                                                 allows the record name to be specified and a unique name to be chosen.
314                                                 By default, the record_file is stored in Asterisk's spool/monitor directory
315                                                 with a unique filename starting with the 'confbridge' prefix.
316                                         </para></description>
317                                 </configOption>
318                                 <configOption name="record_file_append" default="yes">
319                                         <synopsis>Append to record file when starting/stopping on same conference recording</synopsis>
320                                         <description><para>
321                                                 When <replaceable>record_file_append</replaceable> is set to yes, stopping and starting recording on a
322                                                 conference adds the new portion to end of current record_file. When this is
323                                                 set to no, a new <replaceable>record_file</replaceable> is generated every time you start then stop recording
324                                                 on a conference.
325                                         </para></description>
326                                 </configOption>
327                                 <configOption name="record_file_timestamp" default="yes">
328                                         <synopsis>Append the start time to the record_file name so that it is unique.</synopsis>
329                                         <description><para>
330                                                 When <replaceable>record_file_timestamp</replaceable> is set to yes, the start time is appended to
331                                                 <replaceable>record_file</replaceable> so that the filename is unique. This allows you to specify
332                                                 a <replaceable>record_file</replaceable> but not overwrite existing recordings.
333                                         </para></description>
334                                 </configOption>
335                                 <configOption name="record_options" default="">
336                                         <synopsis>Pass additional options to MixMonitor when recording</synopsis>
337                                         <description><para>
338                                                 Pass additional options to MixMonitor when <replaceable>record_conference</replaceable> is set to yes.
339                                                 See <literal>MixMonitor</literal> for available options.
340                                         </para></description>
341                                 </configOption>
342                                 <configOption name="record_command" default="">
343                                         <synopsis>Execute a command after recording ends</synopsis>
344                                         <description><para>
345                                                 Executes the specified command when recording ends. Any strings matching <literal>^{X}</literal> will be
346                                                 unescaped to <variable>X</variable>. All variables will be evaluated at the time ConfBridge is called.
347                                         </para></description>
348                                 </configOption>
349                                 <configOption name="regcontext">
350                                         <synopsis>The name of the context into which to register the name of the conference bridge as NoOP() at priority 1</synopsis>
351                                         <description><para>
352                                                 When set this will cause the name of the created conference to be registered
353                                                 into the named context at priority 1 with an operation of NoOP().  This can
354                                                 then be used in other parts of the dialplan to test for the existence of a
355                                                 specific conference bridge.
356                                                 You should be aware that there are potential races between testing for the
357                                                 existence of a bridge, and taking action upon that information, consider
358                                                 for example two callers executing the check simultaniously, and then taking
359                                                 special action as "first caller" into the bridge.  The same for exiting,
360                                                 directly after the check the bridge can be destroyed before the new caller
361                                                 enters (creating a new bridge), for example, and the "first member" actions
362                                                 could thus be missed.
363                                         </para></description>
364                                 </configOption>
365                                 <configOption name="video_mode">
366                                         <synopsis>Sets how confbridge handles video distribution to the conference participants</synopsis>
367                                         <description><para>
368                                                 Sets how confbridge handles video distribution to the conference participants.
369                                                 Note that participants wanting to view and be the source of a video feed
370                                                 <emphasis>MUST</emphasis> be sharing the same video codec.  Also, using video in conjunction with
371                                                 with the jitterbuffer currently results in the audio being slightly out of sync
372                                                 with the video.  This is a result of the jitterbuffer only working on the audio
373                                                 stream.  It is recommended to disable the jitterbuffer when video is used.</para>
374                                                 <enumlist>
375                                                         <enum name="none">
376                                                                 <para>No video sources are set by default in the conference. It is still
377                                                                 possible for a user to be set as a video source via AMI or DTMF action
378                                                                 at any time.</para>
379                                                         </enum>
380                                                         <enum name="follow_talker">
381                                                                 <para>The video feed will follow whoever is talking and providing video.</para>
382                                                         </enum>
383                                                         <enum name="last_marked">
384                                                                 <para>The last marked user to join the conference with video capabilities
385                                                                 will be the single source of video distributed to all participants.
386                                                                 If multiple marked users are capable of video, the last one to join
387                                                                 is always the source, when that user leaves it goes to the one who
388                                                                 joined before them.</para>
389                                                         </enum>
390                                                         <enum name="first_marked">
391                                                                 <para>The first marked user to join the conference with video capabilities
392                                                                 is the single source of video distribution among all participants. If
393                                                                 that user leaves, the marked user to join after them becomes the source.</para>
394                                                         </enum>
395                                                 </enumlist>
396                                         </description>
397                                 </configOption>
398                                 <configOption name="max_members">
399                                         <synopsis>Limit the maximum number of participants for a single conference</synopsis>
400                                         <description><para>
401                                                 This option limits the number of participants for a single
402                                                 conference to a specific number.  By default conferences
403                                                 have no participant limit. After the limit is reached, the
404                                                 conference will be locked until someone leaves.  Note however
405                                                 that an Admin user will always be alowed to join the conference
406                                                 regardless if this limit is reached or not.
407                                         </para></description>
408                                 </configOption>
409                                 <configOption name="^sound_">
410                                         <synopsis>Override the various conference bridge sound files</synopsis>
411                                         <description><para>
412                                                 All sounds in the conference are customizable using the bridge profile options below.
413                                                 Simply state the option followed by the filename or full path of the filename after
414                                                 the option.  Example: <literal>sound_had_joined=conf-hasjoin</literal>  This will play the <literal>conf-hasjoin</literal>
415                                                 sound file found in the sounds directory when announcing someone's name is joining the
416                                                 conference.</para>
417                                                 <enumlist>
418                                                         <enum name="sound_join"><para>The sound played to everyone when someone enters the conference.</para></enum>
419                                                         <enum name="sound_leave"><para>The sound played to everyone when someone leaves the conference.</para></enum>
420                                                         <enum name="sound_has_joined"><para>The sound played before announcing someone's name has
421                                                                                 joined the conference. This is used for user intros.
422                                                                                 Example <literal>"_____ has joined the conference"</literal></para></enum>
423                                                         <enum name="sound_has_left"><para>The sound played when announcing someone's name has
424                                                                                 left the conference. This is used for user intros.
425                                                                                 Example <literal>"_____ has left the conference"</literal></para></enum>
426                                                         <enum name="sound_kicked"><para>The sound played to a user who has been kicked from the conference.</para></enum>
427                                                         <enum name="sound_muted"><para>The sound played when the mute option it toggled on.</para></enum>
428                                                         <enum name="sound_unmuted"><para>The sound played when the mute option it toggled off.</para></enum>
429                                                         <enum name="sound_only_person"><para>The sound played when the user is the only person in the conference.</para></enum>
430                                                         <enum name="sound_only_one"><para>The sound played to a user when there is only one other
431                                                                                 person is in the conference.</para></enum>
432                                                         <enum name="sound_there_are"><para>The sound played when announcing how many users there
433                                                                                 are in a conference.</para></enum>
434                                                         <enum name="sound_other_in_party"><para>This file is used in conjunction with <literal>sound_there_are</literal>
435                                                                                 when announcing how many users there are in the conference.
436                                                                                 The sounds are stringed together like this.
437                                                                                 <literal>"sound_there_are" ${number of participants} "sound_other_in_party"</literal></para></enum>
438                                                         <enum name="sound_place_into_conference"><para>The sound played when someone is placed into the conference
439                                                                                 after waiting for a marked user.</para></enum>
440                                                         <enum name="sound_wait_for_leader"><para>The sound played when a user is placed into a conference that
441                                                                                 can not start until a marked user enters.</para></enum>
442                                                         <enum name="sound_leader_has_left"><para>The sound played when the last marked user leaves the conference.</para></enum>
443                                                         <enum name="sound_get_pin"><para>The sound played when prompting for a conference pin number.</para></enum>
444                                                         <enum name="sound_invalid_pin"><para>The sound played when an invalid pin is entered too many times.</para></enum>
445                                                         <enum name="sound_locked"><para>The sound played to a user trying to join a locked conference.</para></enum>
446                                                         <enum name="sound_locked_now"><para>The sound played to an admin after toggling the conference to locked mode.</para></enum>
447                                                         <enum name="sound_unlocked_now"><para>The sound played to an admin after toggling the conference to unlocked mode.</para></enum>
448                                                         <enum name="sound_error_menu"><para>The sound played when an invalid menu option is entered.</para></enum>
449                                                 </enumlist>
450                                         </description>
451                                 </configOption>
452                                 <configOption name="template">
453                                         <synopsis>When using the CONFBRIDGE dialplan function, use a bridge profile as a template for creating a new temporary profile</synopsis>
454                                 </configOption>
455                         </configObject>
456                         <configObject name="menu">
457                                 <synopsis>A conference user menu</synopsis>
458                                 <description>
459                                         <para>Conference users, as defined by a <replaceable>conf_user</replaceable>,
460                                         can have a DTMF menu assigned to their profile when they enter the
461                                         <literal>ConfBridge</literal> application.</para>
462                                 </description>
463                                 <configOption name="type">
464                                         <synopsis>Define this configuration category as a menu</synopsis>
465                                         <description><para>The type parameter determines how a context in the
466                                         configuration file is interpreted.</para>
467                                         <enumlist>
468                                                 <enum name="user"><para>Configure the context as a <replaceable>user_profile</replaceable></para></enum>
469                                                 <enum name="bridge"><para>Configure the context as a <replaceable>bridge_profile</replaceable></para></enum>
470                                                 <enum name="menu"><para>Configure the context as a <replaceable>menu</replaceable></para></enum>
471                                         </enumlist>
472                                         </description>
473                                 </configOption>
474                                 <configOption name="template">
475                                         <synopsis>When using the CONFBRIDGE dialplan function, use a menu profile as a template for creating a new temporary profile</synopsis>
476                                 </configOption>
477                                 <configOption name="^[0-9A-D*#]+$">
478                                         <synopsis>DTMF sequences to assign various confbridge actions to</synopsis>
479                                         <description>
480                                         <para>The ConfBridge application also has the ability to apply custom DTMF menus to
481                                         each channel using the application.  Like the User and Bridge profiles a menu
482                                         is passed in to ConfBridge as an argument in the dialplan.</para>
483                                         <para>Below is a list of menu actions that can be assigned to a DTMF sequence.</para>
484                                         <note><para>
485                                                 To have the first DTMF digit in a sequence be the '#' character, you need to
486                                                 escape it.  If it is not escaped then normal config file processing will
487                                                 think it is a directive like #include.  For example: The mute setting is
488                                                 toggled when <literal>#1</literal> is pressed.</para>
489                                                 <para><literal>\#1=toggle_mute</literal></para>
490                                         </note>
491                                         <note><para>
492                                         A single DTMF sequence can have multiple actions associated with it. This is
493                                         accomplished by stringing the actions together and using a <literal>,</literal> as the
494                                         delimiter.  Example:  Both listening and talking volume is reset when <literal>5</literal> is
495                                         pressed.  <literal>5=reset_talking_volume, reset_listening_volume</literal></para></note>
496                                         <enumlist>
497                                                 <enum name="playback(filename&amp;filename2&amp;...)"><para>
498                                                         <literal>playback</literal> will play back an audio file to a channel
499                                                         and then immediately return to the conference.
500                                                         This file can not be interupted by DTMF.
501                                                         Multiple files can be chained together using the
502                                                         <literal>&amp;</literal> character.</para></enum>
503                                                 <enum name="playback_and_continue(filename&amp;filename2&amp;...)"><para>
504                                                         <literal>playback_and_continue</literal> will
505                                                         play back a prompt while continuing to
506                                                         collect the dtmf sequence.  This is useful
507                                                         when using a menu prompt that describes all
508                                                         the menu options.  Note however that any DTMF
509                                                         during this action will terminate the prompts
510                                                         playback.  Prompt files can be chained together
511                                                         using the <literal>&amp;</literal> character as a delimiter.</para></enum>
512                                                 <enum name="toggle_mute"><para>
513                                                         Toggle turning on and off mute.  Mute will make the user silent
514                                                         to everyone else, but the user will still be able to listen in.
515                                                         </para></enum>
516                                                 <enum name="no_op"><para>
517                                                         This action does nothing (No Operation). Its only real purpose exists for
518                                                         being able to reserve a sequence in the config as a menu exit sequence.</para></enum>
519                                                 <enum name="decrease_listening_volume"><para>
520                                                         Decreases the channel's listening volume.</para></enum>
521                                                 <enum name="increase_listening_volume"><para>
522                                                         Increases the channel's listening volume.</para></enum>
523                                                 <enum name="reset_listening_volume"><para>
524                                                         Reset channel's listening volume to default level.</para></enum>
525                                                 <enum name="decrease_talking_volume"><para>
526                                                         Decreases the channel's talking volume.</para></enum>
527                                                 <enum name="increase_talking_volume"><para>
528                                                         Increases the channel's talking volume.</para></enum>
529                                                 <enum name="reset_talking_volume"><para>
530                                                         Reset channel's talking volume to default level.</para></enum>
531                                                 <enum name="dialplan_exec(context,exten,priority)"><para>
532                                                         The <literal>dialplan_exec</literal> action allows a user
533                                                         to escape from the conference and execute
534                                                         commands in the dialplan.  Once the dialplan
535                                                         exits the user will be put back into the
536                                                         conference.  The possibilities are endless!</para></enum>
537                                                 <enum name="leave_conference"><para>
538                                                         This action allows a user to exit the conference and continue
539                                                         execution in the dialplan.</para></enum>
540                                                 <enum name="admin_kick_last"><para>
541                                                         This action allows an Admin to kick the last participant from the
542                                                         conference. This action will only work for admins which allows
543                                                         a single menu to be used for both users and admins.</para></enum>
544                                                 <enum name="admin_toggle_conference_lock"><para>
545                                                         This action allows an Admin to toggle locking and
546                                                         unlocking the conference.  Non admins can not use
547                                                         this action even if it is in their menu.</para></enum>
548                                                 <enum name="set_as_single_video_src"><para>
549                                                         This action allows any user to set themselves as the
550                                                         single video source distributed to all participants.
551                                                         This will make the video feed stick to them regardless
552                                                         of what the <literal>video_mode</literal> is set to.</para></enum>
553                                                 <enum name="release_as_single_video_src"><para>
554                                                         This action allows a user to release themselves as
555                                                         the video source.  If <literal>video_mode</literal> is not set to <literal>none</literal>
556                                                         this action will result in the conference returning to
557                                                         whatever video mode the bridge profile is using.</para>
558                                                         <para>Note that this action will have no effect if the user
559                                                         is not currently the video source.  Also, the user is
560                                                         not guaranteed by using this action that they will not
561                                                         become the video source again.  The bridge will return
562                                                         to whatever operation the <literal>video_mode</literal> option is set to
563                                                         upon release of the video src.</para></enum>
564                                                 <enum name="admin_toggle_mute_participants"><para>
565                                                         This action allows an administrator to toggle the mute
566                                                         state for all non-admins within a conference.  All
567                                                         admin users are unaffected by this option.  Note that all
568                                                         users, regardless of their admin status, are notified
569                                                         that the conference is muted.</para></enum>
570                                                 <enum name="participant_count"><para>
571                                                         This action plays back the number of participants currently
572                                                         in a conference</para></enum>
573                                                 </enumlist>
574                                         </description>
575                                 </configOption>
576                         </configObject>
577                 </configFile>
578         </configInfo>
579 ***/
580
581 struct confbridge_cfg {
582         struct ao2_container *bridge_profiles;
583         struct ao2_container *user_profiles;
584         struct ao2_container *menus;
585 };
586
587 static int verify_default_profiles(void);
588 static void *bridge_profile_alloc(const char *category);
589 static void *bridge_profile_find(struct ao2_container *container, const char *category);
590 static struct bridge_profile_sounds *bridge_profile_sounds_alloc(void);
591
592 static void bridge_profile_destructor(void *obj)
593 {
594         struct bridge_profile *b_profile = obj;
595         ao2_cleanup(b_profile->sounds);
596 }
597
598 static void *bridge_profile_alloc(const char *category)
599 {
600         struct bridge_profile *b_profile;
601
602         if (!(b_profile = ao2_alloc(sizeof(*b_profile), bridge_profile_destructor))) {
603                 return NULL;
604         }
605
606         if (!(b_profile->sounds = bridge_profile_sounds_alloc())) {
607                 ao2_ref(b_profile, -1);
608                 return NULL;
609         }
610
611         ast_copy_string(b_profile->name, category, sizeof(b_profile->name));
612
613         return b_profile;
614 }
615
616 static void *bridge_profile_find(struct ao2_container *container, const char *category)
617 {
618         return ao2_find(container, category, OBJ_KEY);
619 }
620
621 static struct aco_type bridge_type = {
622         .type = ACO_ITEM,
623         .name = "bridge_profile",
624         .category_match = ACO_BLACKLIST,
625         .category = "^general$",
626         .matchfield = "type",
627         .matchvalue = "bridge",
628         .item_alloc = bridge_profile_alloc,
629         .item_find = bridge_profile_find,
630         .item_offset = offsetof(struct confbridge_cfg, bridge_profiles),
631 };
632
633 static void *user_profile_alloc(const char *category);
634 static void *user_profile_find(struct ao2_container *container, const char *category);
635 static void user_profile_destructor(void *obj)
636 {
637         return;
638 }
639
640 static void *user_profile_alloc(const char *category)
641 {
642         struct user_profile *u_profile;
643
644         if (!(u_profile = ao2_alloc(sizeof(*u_profile), user_profile_destructor))) {
645                 return NULL;
646         }
647
648         ast_copy_string(u_profile->name, category, sizeof(u_profile->name));
649
650         return u_profile;
651 }
652
653 static void *user_profile_find(struct ao2_container *container, const char *category)
654 {
655         return ao2_find(container, category, OBJ_KEY);
656 }
657
658 static struct aco_type user_type = {
659         .type = ACO_ITEM,
660         .name  = "user_profile",
661         .category_match = ACO_BLACKLIST,
662         .category = "^general$",
663         .matchfield = "type",
664         .matchvalue = "user",
665         .item_alloc = user_profile_alloc,
666         .item_find = user_profile_find,
667         .item_offset = offsetof(struct confbridge_cfg, user_profiles),
668 };
669
670 static void *menu_alloc(const char *category);
671 static void *menu_find(struct ao2_container *container, const char *category);
672 static void menu_destructor(void *obj);
673
674 static void *menu_alloc(const char *category)
675 {
676         struct conf_menu *menu;
677         if (!(menu = ao2_alloc(sizeof(*menu), menu_destructor))) {
678                 return NULL;
679         }
680         ast_copy_string(menu->name, category, sizeof(menu->name));
681         return menu;
682 }
683
684 static void *menu_find(struct ao2_container *container, const char *category)
685 {
686         return ao2_find(container, category, OBJ_KEY);
687 }
688
689 static struct aco_type menu_type = {
690         .type = ACO_ITEM,
691         .name = "menu",
692         .category_match = ACO_BLACKLIST,
693         .category = "^general$",
694         .matchfield = "type",
695         .matchvalue = "menu",
696         .item_alloc = menu_alloc,
697         .item_find = menu_find,
698         .item_offset = offsetof(struct confbridge_cfg, menus),
699 };
700
701 /* Used to pass to aco_option_register */
702 static struct aco_type *bridge_types[] = ACO_TYPES(&bridge_type);
703 static struct aco_type *menu_types[] = ACO_TYPES(&menu_type);
704 static struct aco_type *user_types[] = ACO_TYPES(&user_type);
705
706 /* The general category is reserved, but unused */
707 static struct aco_type general_type = {
708         .type = ACO_GLOBAL,
709         .name = "global",
710         .category_match = ACO_WHITELIST,
711         .category = "^general$",
712 };
713
714 static struct aco_file confbridge_conf = {
715         .filename = "confbridge.conf",
716         .types = ACO_TYPES(&bridge_type, &user_type, &menu_type, &general_type),
717 };
718
719 static AO2_GLOBAL_OBJ_STATIC(cfg_handle);
720
721 static void *confbridge_cfg_alloc(void);
722
723 CONFIG_INFO_STANDARD(cfg_info, cfg_handle, confbridge_cfg_alloc,
724         .files = ACO_FILES(&confbridge_conf),
725         .pre_apply_config = verify_default_profiles,
726 );
727
728 /*! bridge profile container functions */
729 static int bridge_cmp_cb(void *obj, void *arg, int flags)
730 {
731         const struct bridge_profile *left = obj;
732         const struct bridge_profile *right = arg;
733         const char *right_name = arg;
734         int cmp;
735
736         switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
737         default:
738         case OBJ_POINTER:
739                 right_name = right->name;
740                 /* Fall through */
741         case OBJ_KEY:
742                 cmp = strcasecmp(left->name, right_name);
743                 break;
744         case OBJ_PARTIAL_KEY:
745                 cmp = strncasecmp(left->name, right_name, strlen(right_name));
746                 break;
747         }
748         return cmp ? 0 : CMP_MATCH;
749 }
750
751 static int bridge_hash_cb(const void *obj, const int flags)
752 {
753         const struct bridge_profile *b_profile = obj;
754         const char *name = obj;
755         int hash;
756
757         switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
758         default:
759         case OBJ_POINTER:
760                 name = b_profile->name;
761                 /* Fall through */
762         case OBJ_KEY:
763                 hash = ast_str_case_hash(name);
764                 break;
765         case OBJ_PARTIAL_KEY:
766                 /* Should never happen in hash callback. */
767                 ast_assert(0);
768                 hash = 0;
769                 break;
770         }
771         return hash;
772 }
773
774 /*! menu container functions */
775 static int menu_cmp_cb(void *obj, void *arg, int flags)
776 {
777         const struct conf_menu *left = obj;
778         const struct conf_menu *right = arg;
779         const char *right_name = arg;
780         int cmp;
781
782         switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
783         default:
784         case OBJ_POINTER:
785                 right_name = right->name;
786                 /* Fall through */
787         case OBJ_KEY:
788                 cmp = strcasecmp(left->name, right_name);
789                 break;
790         case OBJ_PARTIAL_KEY:
791                 cmp = strncasecmp(left->name, right_name, strlen(right_name));
792                 break;
793         }
794         return cmp ? 0 : CMP_MATCH;
795 }
796
797 static int menu_hash_cb(const void *obj, const int flags)
798 {
799         const struct conf_menu *menu = obj;
800         const char *name = obj;
801         int hash;
802
803         switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
804         default:
805         case OBJ_POINTER:
806                 name = menu->name;
807                 /* Fall through */
808         case OBJ_KEY:
809                 hash = ast_str_case_hash(name);
810                 break;
811         case OBJ_PARTIAL_KEY:
812                 /* Should never happen in hash callback. */
813                 ast_assert(0);
814                 hash = 0;
815                 break;
816         }
817         return hash;
818 }
819
820 static void menu_destructor(void *obj)
821 {
822         struct conf_menu *menu = obj;
823         struct conf_menu_entry *entry = NULL;
824
825         while ((entry = AST_LIST_REMOVE_HEAD(&menu->entries, entry))) {
826                 conf_menu_entry_destroy(entry);
827                 ast_free(entry);
828         }
829 }
830
831 /*! User profile container functions */
832 static int user_cmp_cb(void *obj, void *arg, int flags)
833 {
834         const struct user_profile *left = obj;
835         const struct user_profile *right = arg;
836         const char *right_name = arg;
837         int cmp;
838
839         switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
840         default:
841         case OBJ_POINTER:
842                 right_name = right->name;
843                 /* Fall through */
844         case OBJ_KEY:
845                 cmp = strcasecmp(left->name, right_name);
846                 break;
847         case OBJ_PARTIAL_KEY:
848                 cmp = strncasecmp(left->name, right_name, strlen(right_name));
849                 break;
850         }
851         return cmp ? 0 : CMP_MATCH;
852 }
853
854 static int user_hash_cb(const void *obj, const int flags)
855 {
856         const struct user_profile *u_profile = obj;
857         const char *name = obj;
858         int hash;
859
860         switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
861         default:
862         case OBJ_POINTER:
863                 name = u_profile->name;
864                 /* Fall through */
865         case OBJ_KEY:
866                 hash = ast_str_case_hash(name);
867                 break;
868         case OBJ_PARTIAL_KEY:
869                 /* Should never happen in hash callback. */
870                 ast_assert(0);
871                 hash = 0;
872                 break;
873         }
874         return hash;
875 }
876
877 /*! Bridge Profile Sounds functions */
878 static void bridge_profile_sounds_destroy_cb(void *obj)
879 {
880         struct bridge_profile_sounds *sounds = obj;
881         ast_string_field_free_memory(sounds);
882 }
883
884 static struct bridge_profile_sounds *bridge_profile_sounds_alloc(void)
885 {
886         struct bridge_profile_sounds *sounds = ao2_alloc(sizeof(*sounds), bridge_profile_sounds_destroy_cb);
887
888         if (!sounds) {
889                 return NULL;
890         }
891         if (ast_string_field_init(sounds, 512)) {
892                 ao2_ref(sounds, -1);
893                 return NULL;
894         }
895
896         return sounds;
897 }
898
899 static int set_sound(const char *sound_name, const char *sound_file, struct bridge_profile *b_profile)
900 {
901         struct bridge_profile_sounds *sounds = b_profile->sounds;
902         if (ast_strlen_zero(sound_file)) {
903                 return -1;
904         }
905
906         if (!strcasecmp(sound_name, "sound_only_person")) {
907                 ast_string_field_set(sounds, onlyperson, sound_file);
908         } else if (!strcasecmp(sound_name, "sound_only_one")) {
909                 ast_string_field_set(sounds, onlyone, sound_file);
910         } else if (!strcasecmp(sound_name, "sound_has_joined")) {
911                 ast_string_field_set(sounds, hasjoin, sound_file);
912         } else if (!strcasecmp(sound_name, "sound_has_left")) {
913                 ast_string_field_set(sounds, hasleft, sound_file);
914         } else if (!strcasecmp(sound_name, "sound_kicked")) {
915                 ast_string_field_set(sounds, kicked, sound_file);
916         } else if (!strcasecmp(sound_name, "sound_muted")) {
917                 ast_string_field_set(sounds, muted, sound_file);
918         } else if (!strcasecmp(sound_name, "sound_unmuted")) {
919                 ast_string_field_set(sounds, unmuted, sound_file);
920         } else if (!strcasecmp(sound_name, "sound_there_are")) {
921                 ast_string_field_set(sounds, thereare, sound_file);
922         } else if (!strcasecmp(sound_name, "sound_other_in_party")) {
923                 ast_string_field_set(sounds, otherinparty, sound_file);
924         } else if (!strcasecmp(sound_name, "sound_place_into_conference")) {
925                 static int deprecation_warning = 1;
926                 if (deprecation_warning) {
927                         ast_log(LOG_WARNING, "sound_place_into_conference is deprecated"
928                                 " and unused. Use sound_begin for similar functionality.");
929                         deprecation_warning = 0;
930                 }
931                 ast_string_field_set(sounds, placeintoconf, sound_file);
932         } else if (!strcasecmp(sound_name, "sound_wait_for_leader")) {
933                 ast_string_field_set(sounds, waitforleader, sound_file);
934         } else if (!strcasecmp(sound_name, "sound_leader_has_left")) {
935                 ast_string_field_set(sounds, leaderhasleft, sound_file);
936         } else if (!strcasecmp(sound_name, "sound_get_pin")) {
937                 ast_string_field_set(sounds, getpin, sound_file);
938         } else if (!strcasecmp(sound_name, "sound_invalid_pin")) {
939                 ast_string_field_set(sounds, invalidpin, sound_file);
940         } else if (!strcasecmp(sound_name, "sound_locked")) {
941                 ast_string_field_set(sounds, locked, sound_file);
942         } else if (!strcasecmp(sound_name, "sound_unlocked_now")) {
943                 ast_string_field_set(sounds, unlockednow, sound_file);
944         } else if (!strcasecmp(sound_name, "sound_locked_now")) {
945                 ast_string_field_set(sounds, lockednow, sound_file);
946         } else if (!strcasecmp(sound_name, "sound_error_menu")) {
947                 ast_string_field_set(sounds, errormenu, sound_file);
948         } else if (!strcasecmp(sound_name, "sound_join")) {
949                 ast_string_field_set(sounds, join, sound_file);
950         } else if (!strcasecmp(sound_name, "sound_leave")) {
951                 ast_string_field_set(sounds, leave, sound_file);
952         } else if (!strcasecmp(sound_name, "sound_participants_muted")) {
953                 ast_string_field_set(sounds, participantsmuted, sound_file);
954         } else if (!strcasecmp(sound_name, "sound_participants_unmuted")) {
955                 ast_string_field_set(sounds, participantsunmuted, sound_file);
956         } else if (!strcasecmp(sound_name, "sound_begin")) {
957                 ast_string_field_set(sounds, begin, sound_file);
958         } else {
959                 return -1;
960         }
961
962         return 0;
963 }
964
965 /*! CONFBRIDGE dialplan function functions and channel datastore. */
966 struct func_confbridge_data {
967         struct bridge_profile b_profile;
968         struct user_profile u_profile;
969         struct conf_menu *menu;
970         unsigned int b_usable:1; /*!< Tells if bridge profile is usable or not */
971         unsigned int u_usable:1; /*!< Tells if user profile is usable or not */
972         unsigned int m_usable:1; /*!< Tells if menu profile is usable or not */
973 };
974
975 static void func_confbridge_data_destructor(struct func_confbridge_data *b_data)
976 {
977         conf_bridge_profile_destroy(&b_data->b_profile);
978         ao2_cleanup(b_data->menu);
979         ast_free(b_data);
980 }
981
982 static void func_confbridge_destroy_cb(void *data)
983 {
984         struct func_confbridge_data *b_data = data;
985         func_confbridge_data_destructor(b_data);
986 };
987
988 static const struct ast_datastore_info confbridge_datastore = {
989         .type = "confbridge",
990         .destroy = func_confbridge_destroy_cb
991 };
992
993 int func_confbridge_helper(struct ast_channel *chan, const char *cmd, char *data, const char *value)
994 {
995         struct ast_datastore *datastore;
996         struct func_confbridge_data *b_data;
997         char *parse;
998         struct ast_variable tmpvar = { 0, };
999         struct ast_variable template = {
1000                 .name = "template",
1001                 .file = "CONFBRIDGE"
1002         };
1003         AST_DECLARE_APP_ARGS(args,
1004                 AST_APP_ARG(type);
1005                 AST_APP_ARG(option);
1006         );
1007
1008         if (!chan) {
1009                 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
1010                 return -1;
1011         }
1012
1013         /* parse all the required arguments and make sure they exist. */
1014         if (ast_strlen_zero(data)) {
1015                 return -1;
1016         }
1017         parse = ast_strdupa(data);
1018         AST_STANDARD_APP_ARGS(args, parse);
1019         if (ast_strlen_zero(args.type) || ast_strlen_zero(args.option)) {
1020                 return -1;
1021         }
1022
1023         ast_channel_lock(chan);
1024         datastore = ast_channel_datastore_find(chan, &confbridge_datastore, NULL);
1025         if (!datastore) {
1026                 datastore = ast_datastore_alloc(&confbridge_datastore, NULL);
1027                 if (!datastore) {
1028                         ast_channel_unlock(chan);
1029                         return 0;
1030                 }
1031                 b_data = ast_calloc(1, sizeof(*b_data));
1032                 if (!b_data) {
1033                         ast_channel_unlock(chan);
1034                         ast_datastore_free(datastore);
1035                         return 0;
1036                 }
1037                 datastore->data = b_data;
1038                 b_data->b_profile.sounds = bridge_profile_sounds_alloc();
1039                 if (!b_data->b_profile.sounds) {
1040                         ast_channel_unlock(chan);
1041                         ast_datastore_free(datastore);
1042                         return 0;
1043                 }
1044                 if (!(b_data->menu = menu_alloc("dialplan"))) {
1045                         ast_channel_unlock(chan);
1046                         ast_datastore_free(datastore);
1047                         return 0;
1048                 }
1049                 ast_channel_datastore_add(chan, datastore);
1050         } else {
1051                 b_data = datastore->data;
1052         }
1053         ast_channel_unlock(chan);
1054
1055         /* SET(CONFBRIDGE(type,option)=value) */
1056         if (!value) {
1057                 value = "";
1058         }
1059         tmpvar.name = args.option;
1060         tmpvar.value = value;
1061         tmpvar.file = "CONFBRIDGE";
1062         if (!strcasecmp(args.type, "bridge")) {
1063                 if (!strcasecmp(args.option, "clear")) {
1064                         b_data->b_usable = 0;
1065                         conf_bridge_profile_destroy(&b_data->b_profile);
1066                         memset(&b_data->b_profile, 0, sizeof(b_data->b_profile)) ;
1067                         if (!(b_data->b_profile.sounds = bridge_profile_sounds_alloc())) {
1068                                 /* If this reallocation fails, the datastore has become unusable and must be destroyed. */
1069                                 ast_channel_lock(chan);
1070                                 ast_channel_datastore_remove(chan, datastore);
1071                                 ast_channel_unlock(chan);
1072                                 ast_datastore_free(datastore);
1073                         }
1074                         return 0;
1075                 }
1076
1077                 if (b_data && !b_data->b_usable && strcasecmp(args.option, "template")) {
1078                         template.value = DEFAULT_BRIDGE_PROFILE;
1079                         aco_process_var(&bridge_type, "dialplan", &template, &b_data->b_profile);
1080                 }
1081
1082                 if (!aco_process_var(&bridge_type, "dialplan", &tmpvar, &b_data->b_profile)) {
1083                         b_data->b_usable = 1;
1084                         return 0;
1085                 }
1086         } else if (!strcasecmp(args.type, "user")) {
1087                 if (!strcasecmp(args.option, "clear")) {
1088                         b_data->u_usable = 0;
1089                         user_profile_destructor(&b_data->u_profile);
1090                         memset(&b_data->u_profile, 0, sizeof(b_data->u_profile));
1091                         return 0;
1092                 }
1093
1094                 if (b_data && !b_data->u_usable && strcasecmp(args.option, "template")) {
1095                         template.value = DEFAULT_USER_PROFILE;
1096                         aco_process_var(&user_type, "dialplan", &template, &b_data->u_profile);
1097                 }
1098
1099                 if (!aco_process_var(&user_type, "dialplan", &tmpvar, &b_data->u_profile)) {
1100                         b_data->u_usable = 1;
1101                         return 0;
1102                 }
1103         } else if (!strcasecmp(args.type, "menu")) {
1104                 if (!strcasecmp(args.option, "clear")) {
1105                         b_data->m_usable = 0;
1106                         ao2_cleanup(b_data->menu);
1107                         if (!(b_data->menu = menu_alloc("dialplan"))) {
1108                                 /* If this reallocation fails, the datastore has become unusable and must be destroyed */
1109                                 ast_channel_lock(chan);
1110                                 ast_channel_datastore_remove(chan, datastore);
1111                                 ast_channel_unlock(chan);
1112                                 ast_datastore_free(datastore);
1113                         }
1114                         return 0;
1115                 }
1116
1117                 if (b_data && !b_data->m_usable && strcasecmp(args.option, "template")) {
1118                         template.value = DEFAULT_MENU_PROFILE;
1119                         aco_process_var(&menu_type, "dialplan", &template, &b_data->menu);
1120                 }
1121
1122                 if (!aco_process_var(&menu_type, "dialplan", &tmpvar, b_data->menu)) {
1123                         b_data->m_usable = 1;
1124                         return 0;
1125                 }
1126         }
1127
1128         ast_log(LOG_WARNING, "%s(%s,%s) cannot be set to '%s'. Invalid type, option, or value.\n",
1129                 cmd, args.type, args.option, value);
1130         return -1;
1131 }
1132
1133 static int add_action_to_menu_entry(struct conf_menu_entry *menu_entry, enum conf_menu_action_id id, char *databuf)
1134 {
1135         struct conf_menu_action *menu_action = ast_calloc(1, sizeof(*menu_action));
1136
1137         if (!menu_action) {
1138                 return -1;
1139         }
1140         menu_action->id = id;
1141
1142         switch (id) {
1143         case MENU_ACTION_NOOP:
1144         case MENU_ACTION_TOGGLE_MUTE:
1145         case MENU_ACTION_INCREASE_LISTENING:
1146         case MENU_ACTION_DECREASE_LISTENING:
1147         case MENU_ACTION_INCREASE_TALKING:
1148         case MENU_ACTION_DECREASE_TALKING:
1149         case MENU_ACTION_RESET_LISTENING:
1150         case MENU_ACTION_RESET_TALKING:
1151         case MENU_ACTION_ADMIN_TOGGLE_LOCK:
1152         case MENU_ACTION_ADMIN_TOGGLE_MUTE_PARTICIPANTS:
1153         case MENU_ACTION_PARTICIPANT_COUNT:
1154         case MENU_ACTION_ADMIN_KICK_LAST:
1155         case MENU_ACTION_LEAVE:
1156         case MENU_ACTION_SET_SINGLE_VIDEO_SRC:
1157         case MENU_ACTION_RELEASE_SINGLE_VIDEO_SRC:
1158                 break;
1159         case MENU_ACTION_PLAYBACK:
1160         case MENU_ACTION_PLAYBACK_AND_CONTINUE:
1161                 if (!(ast_strlen_zero(databuf))) {
1162                         ast_copy_string(menu_action->data.playback_file, databuf, sizeof(menu_action->data.playback_file));
1163                 } else {
1164                         ast_free(menu_action);
1165                         return -1;
1166                 }
1167                 break;
1168         case MENU_ACTION_DIALPLAN_EXEC:
1169                 if (!(ast_strlen_zero(databuf))) {
1170                         AST_DECLARE_APP_ARGS(args,
1171                                 AST_APP_ARG(context);
1172                                 AST_APP_ARG(exten);
1173                                 AST_APP_ARG(priority);
1174                         );
1175                         AST_STANDARD_APP_ARGS(args, databuf);
1176                         if (!ast_strlen_zero(args.context)) {
1177                                 ast_copy_string(menu_action->data.dialplan_args.context,
1178                                         args.context,
1179                                         sizeof(menu_action->data.dialplan_args.context));
1180                         }
1181                         if (!ast_strlen_zero(args.exten)) {
1182                                 ast_copy_string(menu_action->data.dialplan_args.exten,
1183                                         args.exten,
1184                                         sizeof(menu_action->data.dialplan_args.exten));
1185                         }
1186                         menu_action->data.dialplan_args.priority = 1; /* 1 by default */
1187                         if (!ast_strlen_zero(args.priority) &&
1188                                 (sscanf(args.priority, "%30d", &menu_action->data.dialplan_args.priority) != 1)) {
1189                                 /* invalid priority */
1190                                 ast_free(menu_action);
1191                                 return -1;
1192                         }
1193                 } else {
1194                         ast_free(menu_action);
1195                         return -1;
1196                 }
1197         };
1198
1199         AST_LIST_INSERT_TAIL(&menu_entry->actions, menu_action, action);
1200
1201         return 0;
1202 }
1203
1204 static int add_menu_entry(struct conf_menu *menu, const char *dtmf, const char *action_names)
1205 {
1206         struct conf_menu_entry *menu_entry = NULL, *cur = NULL;
1207         int res = 0;
1208         char *tmp_action_names = ast_strdupa(action_names);
1209         char *action = NULL;
1210         char *action_args;
1211         char *tmp;
1212         char buf[PATH_MAX];
1213         char *delimiter = ",";
1214
1215         if (!(menu_entry = ast_calloc(1, sizeof(*menu_entry)))) {
1216                 return -1;
1217         }
1218
1219         for (;;) {
1220                 char *comma;
1221                 char *startbrace;
1222                 char *endbrace;
1223                 unsigned int action_len;
1224
1225                 if (ast_strlen_zero(tmp_action_names)) {
1226                         break;
1227                 }
1228                 startbrace = strchr(tmp_action_names, '(');
1229                 endbrace = strchr(tmp_action_names, ')');
1230                 comma = strchr(tmp_action_names, ',');
1231
1232                 /* If the next action has brackets with comma delimited arguments in it,
1233                  * make the delimeter ')' instead of a comma to preserve the argments */
1234                 if (startbrace && endbrace && comma && (comma > startbrace && comma < endbrace)) {
1235                         delimiter = ")";
1236                 } else {
1237                         delimiter = ",";
1238                 }
1239
1240                 if (!(action = strsep(&tmp_action_names, delimiter))) {
1241                         break;
1242                 }
1243
1244                 action = ast_strip(action);
1245                 if (ast_strlen_zero(action)) {
1246                         continue;
1247                 }
1248
1249                 action_len = strlen(action);
1250                 ast_copy_string(menu_entry->dtmf, dtmf, sizeof(menu_entry->dtmf));
1251                 if (!strcasecmp(action, "toggle_mute")) {
1252                         res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_TOGGLE_MUTE, NULL);
1253                 } else if (!strcasecmp(action, "no_op")) {
1254                         res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_NOOP, NULL);
1255                 } else if (!strcasecmp(action, "increase_listening_volume")) {
1256                         res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_INCREASE_LISTENING, NULL);
1257                 } else if (!strcasecmp(action, "decrease_listening_volume")) {
1258                         res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_DECREASE_LISTENING, NULL);
1259                 } else if (!strcasecmp(action, "increase_talking_volume")) {
1260                         res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_INCREASE_TALKING, NULL);
1261                 } else if (!strcasecmp(action, "reset_listening_volume")) {
1262                         res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_RESET_LISTENING, NULL);
1263                 } else if (!strcasecmp(action, "reset_talking_volume")) {
1264                         res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_RESET_TALKING, NULL);
1265                 } else if (!strcasecmp(action, "decrease_talking_volume")) {
1266                         res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_DECREASE_TALKING, NULL);
1267                 } else if (!strcasecmp(action, "admin_toggle_conference_lock")) {
1268                         res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_ADMIN_TOGGLE_LOCK, NULL);
1269                 } else if (!strcasecmp(action, "admin_toggle_mute_participants")) {
1270                         res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_ADMIN_TOGGLE_MUTE_PARTICIPANTS, NULL);
1271                 } else if (!strcasecmp(action, "participant_count")) {
1272                         res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_PARTICIPANT_COUNT, NULL);
1273                 } else if (!strcasecmp(action, "admin_kick_last")) {
1274                         res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_ADMIN_KICK_LAST, NULL);
1275                 } else if (!strcasecmp(action, "leave_conference")) {
1276                         res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_LEAVE, NULL);
1277                 } else if (!strcasecmp(action, "set_as_single_video_src")) {
1278                         res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_SET_SINGLE_VIDEO_SRC, NULL);
1279                 } else if (!strcasecmp(action, "release_as_single_video_src")) {
1280                         res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_RELEASE_SINGLE_VIDEO_SRC, NULL);
1281                 } else if (!strncasecmp(action, "dialplan_exec(", 14)) {
1282                         ast_copy_string(buf, action, sizeof(buf));
1283                         action_args = buf;
1284                         if ((action_args = strchr(action, '('))) {
1285                                 action_args++;
1286                         }
1287                         /* it is possible that this argument may or may not
1288                          * have a closing brace at this point, it all depends on if
1289                          * comma delimited arguments were provided */
1290                         if ((tmp = strchr(action, ')'))) {
1291                                 *tmp = '\0';
1292                         }
1293                         res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_DIALPLAN_EXEC, action_args);
1294                 } else if (action_len >= 21 && !strncasecmp(action, "playback_and_continue(", 22)) {
1295                         ast_copy_string(buf, action, sizeof(buf));
1296                         action_args = buf;
1297                         if ((action_args = strchr(action, '(')) && (tmp = strrchr(action_args, ')'))) {
1298                                 *tmp = '\0';
1299                                 action_args++;
1300                         }
1301                         res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_PLAYBACK_AND_CONTINUE, action_args);
1302                 } else if (action_len >= 8 && !strncasecmp(action, "playback(", 9)) {
1303                         ast_copy_string(buf, action, sizeof(buf));
1304                         action_args = buf;
1305                         if ((action_args = strchr(action, '(')) && (tmp = strrchr(action_args, ')'))) {
1306                                 *tmp = '\0';
1307                                 action_args++;
1308                         }
1309                         res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_PLAYBACK, action_args);
1310                 }
1311         }
1312
1313         /* if adding any of the actions failed, bail */
1314         if (res) {
1315                 struct conf_menu_action *menu_action;
1316                 while ((menu_action = AST_LIST_REMOVE_HEAD(&menu_entry->actions, action))) {
1317                         ast_free(menu_action);
1318                 }
1319                 ast_free(menu_entry);
1320                 return -1;
1321         }
1322
1323         /* remove any list entry with an identical DTMF sequence for overrides */
1324         AST_LIST_TRAVERSE_SAFE_BEGIN(&menu->entries, cur, entry) {
1325                 if (!strcasecmp(cur->dtmf, menu_entry->dtmf)) {
1326                         AST_LIST_REMOVE_CURRENT(entry);
1327                         ast_free(cur);
1328                         break;
1329                 }
1330         }
1331         AST_LIST_TRAVERSE_SAFE_END;
1332
1333         AST_LIST_INSERT_TAIL(&menu->entries, menu_entry, entry);
1334
1335         return 0;
1336 }
1337
1338 static char *complete_user_profile_name(const char *line, const char *word, int pos, int state)
1339 {
1340         int which = 0;
1341         char *res = NULL;
1342         int wordlen = strlen(word);
1343         struct ao2_iterator i;
1344         struct user_profile *u_profile = NULL;
1345         RAII_VAR(struct confbridge_cfg *, cfg, ao2_global_obj_ref(cfg_handle), ao2_cleanup);
1346
1347         if (!cfg) {
1348                 return NULL;
1349         }
1350
1351         i = ao2_iterator_init(cfg->user_profiles, 0);
1352         while ((u_profile = ao2_iterator_next(&i))) {
1353                 if (!strncasecmp(u_profile->name, word, wordlen) && ++which > state) {
1354                         res = ast_strdup(u_profile->name);
1355                         ao2_ref(u_profile, -1);
1356                         break;
1357                 }
1358                 ao2_ref(u_profile, -1);
1359         }
1360         ao2_iterator_destroy(&i);
1361
1362         return res;
1363 }
1364
1365 static char *handle_cli_confbridge_show_user_profiles(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1366 {
1367         struct ao2_iterator it;
1368         struct user_profile *u_profile;
1369         RAII_VAR(struct confbridge_cfg *, cfg, NULL, ao2_cleanup);
1370
1371         switch (cmd) {
1372         case CLI_INIT:
1373                 e->command = "confbridge show profile users";
1374                 e->usage =
1375                         "Usage confbridge show profile users\n";
1376                 return NULL;
1377         case CLI_GENERATE:
1378                 return NULL;
1379         }
1380
1381         if (!(cfg = ao2_global_obj_ref(cfg_handle))) {
1382                 return NULL;
1383         }
1384
1385         ast_cli(a->fd,"--------- User Profiles -----------\n");
1386         ao2_lock(cfg->user_profiles);
1387         it = ao2_iterator_init(cfg->user_profiles, 0);
1388         while ((u_profile = ao2_iterator_next(&it))) {
1389                 ast_cli(a->fd,"%s\n", u_profile->name);
1390                 ao2_ref(u_profile, -1);
1391         }
1392         ao2_iterator_destroy(&it);
1393         ao2_unlock(cfg->user_profiles);
1394
1395         return CLI_SUCCESS;
1396 }
1397 static char *handle_cli_confbridge_show_user_profile(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1398 {
1399         struct user_profile u_profile;
1400
1401         switch (cmd) {
1402         case CLI_INIT:
1403                 e->command = "confbridge show profile user";
1404                 e->usage =
1405                         "Usage confbridge show profile user [<profile name>]\n";
1406                 return NULL;
1407         case CLI_GENERATE:
1408                 if (a->pos == 4) {
1409                         return complete_user_profile_name(a->line, a->word, a->pos, a->n);
1410                 }
1411                 return NULL;
1412         }
1413
1414         if (a->argc != 5) {
1415                 return CLI_SHOWUSAGE;
1416         }
1417
1418         if (!(conf_find_user_profile(NULL, a->argv[4], &u_profile))) {
1419                 ast_cli(a->fd, "No conference user profile named '%s' found!\n", a->argv[4]);
1420                 return CLI_SUCCESS;
1421         }
1422
1423         ast_cli(a->fd,"--------------------------------------------\n");
1424         ast_cli(a->fd,"Name:                    %s\n",
1425                 u_profile.name);
1426         ast_cli(a->fd,"Admin:                   %s\n",
1427                 u_profile.flags & USER_OPT_ADMIN ?
1428                 "true" : "false");
1429         ast_cli(a->fd,"Marked User:             %s\n",
1430                 u_profile.flags & USER_OPT_MARKEDUSER ?
1431                 "true" : "false");
1432         ast_cli(a->fd,"Start Muted:             %s\n",
1433                 u_profile.flags & USER_OPT_STARTMUTED?
1434                 "true" : "false");
1435         ast_cli(a->fd,"MOH When Empty:          %s\n",
1436                 u_profile.flags & USER_OPT_MUSICONHOLD ?
1437                 "enabled" : "disabled");
1438         ast_cli(a->fd,"MOH Class:               %s\n",
1439                 ast_strlen_zero(u_profile.moh_class) ?
1440                 "default" : u_profile.moh_class);
1441         ast_cli(a->fd,"Announcement:            %s\n",
1442                 u_profile.announcement);
1443         ast_cli(a->fd,"Quiet:                   %s\n",
1444                 u_profile.flags & USER_OPT_QUIET ?
1445                 "enabled" : "disabled");
1446         ast_cli(a->fd,"Wait Marked:             %s\n",
1447                 u_profile.flags & USER_OPT_WAITMARKED ?
1448                 "enabled" : "disabled");
1449         ast_cli(a->fd,"END Marked:              %s\n",
1450                 u_profile.flags & USER_OPT_ENDMARKED ?
1451                 "enabled" : "disabled");
1452         ast_cli(a->fd,"Drop_silence:            %s\n",
1453                 u_profile.flags & USER_OPT_DROP_SILENCE ?
1454                 "enabled" : "disabled");
1455         ast_cli(a->fd,"Silence Threshold:       %ums\n",
1456                 u_profile.silence_threshold);
1457         ast_cli(a->fd,"Talking Threshold:       %ums\n",
1458                 u_profile.talking_threshold);
1459         ast_cli(a->fd,"Denoise:                 %s\n",
1460                 u_profile.flags & USER_OPT_DENOISE ?
1461                 "enabled" : "disabled");
1462         ast_cli(a->fd,"Jitterbuffer:            %s\n",
1463                 u_profile.flags & USER_OPT_JITTERBUFFER ?
1464                 "enabled" : "disabled");
1465         ast_cli(a->fd,"Talk Detect Events:      %s\n",
1466                 u_profile.flags & USER_OPT_TALKER_DETECT ?
1467                 "enabled" : "disabled");
1468         ast_cli(a->fd,"DTMF Pass Through:       %s\n",
1469                 u_profile.flags & USER_OPT_DTMF_PASS ?
1470                 "enabled" : "disabled");
1471         ast_cli(a->fd,"PIN:                     %s\n",
1472                 ast_strlen_zero(u_profile.pin) ?
1473                 "None" : u_profile.pin);
1474         ast_cli(a->fd,"Announce User Count:     %s\n",
1475                 u_profile.flags & USER_OPT_ANNOUNCEUSERCOUNT ?
1476                 "enabled" : "disabled");
1477         ast_cli(a->fd,"Announce join/leave:     %s\n",
1478                 u_profile.flags & (USER_OPT_ANNOUNCE_JOIN_LEAVE | USER_OPT_ANNOUNCE_JOIN_LEAVE_REVIEW) ?
1479                 u_profile.flags & USER_OPT_ANNOUNCE_JOIN_LEAVE_REVIEW ?
1480                 "enabled (with review)" : "enabled" : "disabled");
1481         ast_cli(a->fd,"Announce User Count all: %s\n",
1482                 u_profile.flags & USER_OPT_ANNOUNCEUSERCOUNTALL ?
1483                 "enabled" : "disabled");
1484                 ast_cli(a->fd,"\n");
1485
1486         return CLI_SUCCESS;
1487 }
1488
1489 static char *complete_bridge_profile_name(const char *line, const char *word, int pos, int state)
1490 {
1491         int which = 0;
1492         char *res = NULL;
1493         int wordlen = strlen(word);
1494         struct ao2_iterator i;
1495         struct bridge_profile *b_profile = NULL;
1496         RAII_VAR(struct confbridge_cfg *, cfg, ao2_global_obj_ref(cfg_handle), ao2_cleanup);
1497
1498         if (!cfg) {
1499                 return NULL;
1500         }
1501
1502         i = ao2_iterator_init(cfg->bridge_profiles, 0);
1503         while ((b_profile = ao2_iterator_next(&i))) {
1504                 if (!strncasecmp(b_profile->name, word, wordlen) && ++which > state) {
1505                         res = ast_strdup(b_profile->name);
1506                         ao2_ref(b_profile, -1);
1507                         break;
1508                 }
1509                 ao2_ref(b_profile, -1);
1510         }
1511         ao2_iterator_destroy(&i);
1512
1513         return res;
1514 }
1515
1516 static char *handle_cli_confbridge_show_bridge_profiles(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1517 {
1518         struct ao2_iterator it;
1519         struct bridge_profile *b_profile;
1520         RAII_VAR(struct confbridge_cfg *, cfg, NULL, ao2_cleanup);
1521
1522         switch (cmd) {
1523         case CLI_INIT:
1524                 e->command = "confbridge show profile bridges";
1525                 e->usage =
1526                         "Usage confbridge show profile bridges\n";
1527                 return NULL;
1528         case CLI_GENERATE:
1529                 return NULL;
1530         }
1531
1532         if (!(cfg = ao2_global_obj_ref(cfg_handle))) {
1533                 return NULL;
1534         }
1535
1536         ast_cli(a->fd,"--------- Bridge Profiles -----------\n");
1537         ao2_lock(cfg->bridge_profiles);
1538         it = ao2_iterator_init(cfg->bridge_profiles, 0);
1539         while ((b_profile = ao2_iterator_next(&it))) {
1540                 ast_cli(a->fd,"%s\n", b_profile->name);
1541                 ao2_ref(b_profile, -1);
1542         }
1543         ao2_iterator_destroy(&it);
1544         ao2_unlock(cfg->bridge_profiles);
1545
1546         return CLI_SUCCESS;
1547 }
1548
1549 static char *handle_cli_confbridge_show_bridge_profile(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1550 {
1551         struct bridge_profile b_profile;
1552         char tmp[64];
1553
1554         switch (cmd) {
1555         case CLI_INIT:
1556                 e->command = "confbridge show profile bridge";
1557                 e->usage =
1558                         "Usage confbridge show profile bridge <profile name>\n";
1559                 return NULL;
1560         case CLI_GENERATE:
1561                 if (a->pos == 4) {
1562                         return complete_bridge_profile_name(a->line, a->word, a->pos, a->n);
1563                 }
1564                 return NULL;
1565         }
1566
1567         if (a->argc != 5) {
1568                 return CLI_SHOWUSAGE;
1569         }
1570
1571         if (!(conf_find_bridge_profile(NULL, a->argv[4], &b_profile))) {
1572                 ast_cli(a->fd, "No conference bridge profile named '%s' found!\n", a->argv[4]);
1573                 return CLI_SUCCESS;
1574         }
1575
1576         ast_cli(a->fd,"--------------------------------------------\n");
1577         ast_cli(a->fd,"Name:                 %s\n", b_profile.name);
1578         ast_cli(a->fd,"Language:             %s\n", b_profile.language);
1579
1580         if (b_profile.internal_sample_rate) {
1581                 snprintf(tmp, sizeof(tmp), "%u", b_profile.internal_sample_rate);
1582         } else {
1583                 ast_copy_string(tmp, "auto", sizeof(tmp));
1584         }
1585         ast_cli(a->fd,"Internal Sample Rate: %s\n", tmp);
1586
1587         if (b_profile.mix_interval) {
1588                 ast_cli(a->fd,"Mixing Interval:      %u\n", b_profile.mix_interval);
1589         } else {
1590                 ast_cli(a->fd,"Mixing Interval:      Default 20ms\n");
1591         }
1592
1593         ast_cli(a->fd,"Record Conference:    %s\n",
1594                 b_profile.flags & BRIDGE_OPT_RECORD_CONFERENCE ?
1595                 "yes" : "no");
1596
1597         ast_cli(a->fd,"Record File Append:    %s\n",
1598                 b_profile.flags & BRIDGE_OPT_RECORD_FILE_APPEND ?
1599                 "yes" : "no");
1600
1601         ast_cli(a->fd,"Record File Timestamp: %s\n",
1602                 b_profile.flags & BRIDGE_OPT_RECORD_FILE_TIMESTAMP ?
1603                 "yes" : "no");
1604
1605         ast_cli(a->fd,"Record File:          %s\n",
1606                 ast_strlen_zero(b_profile.rec_file) ? "Auto Generated" :
1607                 b_profile.rec_file);
1608
1609         ast_cli(a->fd,"Record Options:       %s\n",
1610                 b_profile.rec_options);
1611
1612         ast_cli(a->fd,"Record Command:       %s\n",
1613                 b_profile.rec_command);
1614
1615         if (b_profile.max_members) {
1616                 ast_cli(a->fd,"Max Members:          %u\n", b_profile.max_members);
1617         } else {
1618                 ast_cli(a->fd,"Max Members:          No Limit\n");
1619         }
1620
1621         ast_cli(a->fd,"Registration context: %s\n", b_profile.regcontext);
1622
1623         switch (b_profile.flags
1624                 & (BRIDGE_OPT_VIDEO_SRC_LAST_MARKED | BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED
1625                         | BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER)) {
1626         case BRIDGE_OPT_VIDEO_SRC_LAST_MARKED:
1627                 ast_cli(a->fd, "Video Mode:           last_marked\n");
1628                 break;
1629         case BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED:
1630                 ast_cli(a->fd, "Video Mode:           first_marked\n");
1631                 break;
1632         case BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER:
1633                 ast_cli(a->fd, "Video Mode:           follow_talker\n");
1634                 break;
1635         case 0:
1636                 ast_cli(a->fd, "Video Mode:           no video\n");
1637                 break;
1638         default:
1639                 /* Opps.  We have more than one video mode flag set. */
1640                 ast_assert(0);
1641                 break;
1642         }
1643
1644         ast_cli(a->fd,"sound_only_person:    %s\n", conf_get_sound(CONF_SOUND_ONLY_PERSON, b_profile.sounds));
1645         ast_cli(a->fd,"sound_only_one:       %s\n", conf_get_sound(CONF_SOUND_ONLY_ONE, b_profile.sounds));
1646         ast_cli(a->fd,"sound_has_joined:     %s\n", conf_get_sound(CONF_SOUND_HAS_JOINED, b_profile.sounds));
1647         ast_cli(a->fd,"sound_has_left:       %s\n", conf_get_sound(CONF_SOUND_HAS_LEFT, b_profile.sounds));
1648         ast_cli(a->fd,"sound_kicked:         %s\n", conf_get_sound(CONF_SOUND_KICKED, b_profile.sounds));
1649         ast_cli(a->fd,"sound_muted:          %s\n", conf_get_sound(CONF_SOUND_MUTED, b_profile.sounds));
1650         ast_cli(a->fd,"sound_unmuted:        %s\n", conf_get_sound(CONF_SOUND_UNMUTED, b_profile.sounds));
1651         ast_cli(a->fd,"sound_there_are:      %s\n", conf_get_sound(CONF_SOUND_THERE_ARE, b_profile.sounds));
1652         ast_cli(a->fd,"sound_other_in_party: %s\n", conf_get_sound(CONF_SOUND_OTHER_IN_PARTY, b_profile.sounds));
1653         ast_cli(a->fd,"sound_place_into_conference: %s\n", conf_get_sound(CONF_SOUND_PLACE_IN_CONF, b_profile.sounds));
1654         ast_cli(a->fd,"sound_wait_for_leader:       %s\n", conf_get_sound(CONF_SOUND_WAIT_FOR_LEADER, b_profile.sounds));
1655         ast_cli(a->fd,"sound_leader_has_left:       %s\n", conf_get_sound(CONF_SOUND_LEADER_HAS_LEFT, b_profile.sounds));
1656         ast_cli(a->fd,"sound_get_pin:        %s\n", conf_get_sound(CONF_SOUND_GET_PIN, b_profile.sounds));
1657         ast_cli(a->fd,"sound_invalid_pin:    %s\n", conf_get_sound(CONF_SOUND_INVALID_PIN, b_profile.sounds));
1658         ast_cli(a->fd,"sound_locked:         %s\n", conf_get_sound(CONF_SOUND_LOCKED, b_profile.sounds));
1659         ast_cli(a->fd,"sound_unlocked_now:   %s\n", conf_get_sound(CONF_SOUND_UNLOCKED_NOW, b_profile.sounds));
1660         ast_cli(a->fd,"sound_lockednow:      %s\n", conf_get_sound(CONF_SOUND_LOCKED_NOW, b_profile.sounds));
1661         ast_cli(a->fd,"sound_error_menu:     %s\n", conf_get_sound(CONF_SOUND_ERROR_MENU, b_profile.sounds));
1662         ast_cli(a->fd,"sound_join:           %s\n", conf_get_sound(CONF_SOUND_JOIN, b_profile.sounds));
1663         ast_cli(a->fd,"sound_leave:          %s\n", conf_get_sound(CONF_SOUND_LEAVE, b_profile.sounds));
1664         ast_cli(a->fd,"sound_participants_muted:     %s\n", conf_get_sound(CONF_SOUND_PARTICIPANTS_MUTED, b_profile.sounds));
1665         ast_cli(a->fd,"sound_participants_unmuted:     %s\n", conf_get_sound(CONF_SOUND_PARTICIPANTS_UNMUTED, b_profile.sounds));
1666         ast_cli(a->fd,"sound_begin:          %s\n", conf_get_sound(CONF_SOUND_BEGIN, b_profile.sounds));
1667         ast_cli(a->fd,"\n");
1668
1669         conf_bridge_profile_destroy(&b_profile);
1670         return CLI_SUCCESS;
1671 }
1672
1673 static char *complete_menu_name(const char *line, const char *word, int pos, int state)
1674 {
1675         int which = 0;
1676         char *res = NULL;
1677         int wordlen = strlen(word);
1678         struct ao2_iterator i;
1679         struct conf_menu *menu = NULL;
1680         RAII_VAR(struct confbridge_cfg *, cfg, ao2_global_obj_ref(cfg_handle), ao2_cleanup);
1681
1682         if (!cfg) {
1683                 return NULL;
1684         }
1685
1686         i = ao2_iterator_init(cfg->menus, 0);
1687         while ((menu = ao2_iterator_next(&i))) {
1688                 if (!strncasecmp(menu->name, word, wordlen) && ++which > state) {
1689                         res = ast_strdup(menu->name);
1690                         ao2_ref(menu, -1);
1691                         break;
1692                 }
1693                 ao2_ref(menu, -1);
1694         }
1695         ao2_iterator_destroy(&i);
1696
1697         return res;
1698 }
1699
1700 static char *handle_cli_confbridge_show_menus(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1701 {
1702         struct ao2_iterator it;
1703         struct conf_menu *menu;
1704         RAII_VAR(struct confbridge_cfg *, cfg, NULL, ao2_cleanup);
1705
1706         switch (cmd) {
1707         case CLI_INIT:
1708                 e->command = "confbridge show menus";
1709                 e->usage =
1710                         "Usage confbridge show profile menus\n";
1711                 return NULL;
1712         case CLI_GENERATE:
1713                 return NULL;
1714         }
1715
1716         if (!(cfg = ao2_global_obj_ref(cfg_handle))) {
1717                 return NULL;
1718         }
1719
1720         ast_cli(a->fd,"--------- Menus -----------\n");
1721         ao2_lock(cfg->menus);
1722         it = ao2_iterator_init(cfg->menus, 0);
1723         while ((menu = ao2_iterator_next(&it))) {
1724                 ast_cli(a->fd,"%s\n", menu->name);
1725                 ao2_ref(menu, -1);
1726         }
1727         ao2_iterator_destroy(&it);
1728         ao2_unlock(cfg->menus);
1729
1730         return CLI_SUCCESS;
1731 }
1732
1733 static char *handle_cli_confbridge_show_menu(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1734 {
1735         RAII_VAR(struct conf_menu *, menu, NULL, ao2_cleanup);
1736         RAII_VAR(struct confbridge_cfg *, cfg, NULL, ao2_cleanup);
1737         struct conf_menu_entry *menu_entry = NULL;
1738         struct conf_menu_action *menu_action = NULL;
1739
1740         switch (cmd) {
1741         case CLI_INIT:
1742                 e->command = "confbridge show menu";
1743                 e->usage =
1744                         "Usage confbridge show menu [<menu name>]\n";
1745                 return NULL;
1746         case CLI_GENERATE:
1747                 if (a->pos == 3) {
1748                         return complete_menu_name(a->line, a->word, a->pos, a->n);
1749                 }
1750                 return NULL;
1751         }
1752
1753         if (a->argc != 4) {
1754                 return CLI_SHOWUSAGE;
1755         }
1756
1757         if (!(cfg = ao2_global_obj_ref(cfg_handle))) {
1758                 return NULL;
1759         }
1760
1761         if (!(menu = menu_find(cfg->menus, a->argv[3]))) {
1762                 ast_cli(a->fd, "No conference menu named '%s' found!\n", a->argv[3]);
1763                 return CLI_SUCCESS;
1764         }
1765         ao2_lock(menu);
1766
1767         ast_cli(a->fd,"Name: %s\n", menu->name);
1768         AST_LIST_TRAVERSE(&menu->entries, menu_entry, entry) {
1769                 int action_num = 0;
1770                 ast_cli(a->fd, "%s=", menu_entry->dtmf);
1771                 AST_LIST_TRAVERSE(&menu_entry->actions, menu_action, action) {
1772                         if (action_num) {
1773                                 ast_cli(a->fd, ", ");
1774                         }
1775                         switch (menu_action->id) {
1776                         case MENU_ACTION_TOGGLE_MUTE:
1777                                 ast_cli(a->fd, "toggle_mute");
1778                                 break;
1779                         case MENU_ACTION_NOOP:
1780                                 ast_cli(a->fd, "no_op");
1781                                 break;
1782                         case MENU_ACTION_INCREASE_LISTENING:
1783                                 ast_cli(a->fd, "increase_listening_volume");
1784                                 break;
1785                         case MENU_ACTION_DECREASE_LISTENING:
1786                                 ast_cli(a->fd, "decrease_listening_volume");
1787                                 break;
1788                         case MENU_ACTION_RESET_LISTENING:
1789                                 ast_cli(a->fd, "reset_listening_volume");
1790                                 break;
1791                         case MENU_ACTION_RESET_TALKING:
1792                                 ast_cli(a->fd, "reset_talking_volume");
1793                                 break;
1794                         case MENU_ACTION_INCREASE_TALKING:
1795                                 ast_cli(a->fd, "increase_talking_volume");
1796                                 break;
1797                         case MENU_ACTION_DECREASE_TALKING:
1798                                 ast_cli(a->fd, "decrease_talking_volume");
1799                                 break;
1800                         case MENU_ACTION_PLAYBACK:
1801                                 ast_cli(a->fd, "playback(%s)", menu_action->data.playback_file);
1802                                 break;
1803                         case MENU_ACTION_PLAYBACK_AND_CONTINUE:
1804                                 ast_cli(a->fd, "playback_and_continue(%s)", menu_action->data.playback_file);
1805                                 break;
1806                         case MENU_ACTION_DIALPLAN_EXEC:
1807                                 ast_cli(a->fd, "dialplan_exec(%s,%s,%d)",
1808                                         menu_action->data.dialplan_args.context,
1809                                         menu_action->data.dialplan_args.exten,
1810                                         menu_action->data.dialplan_args.priority);
1811                                 break;
1812                         case MENU_ACTION_ADMIN_TOGGLE_LOCK:
1813                                 ast_cli(a->fd, "admin_toggle_conference_lock");
1814                                 break;
1815                         case MENU_ACTION_ADMIN_TOGGLE_MUTE_PARTICIPANTS:
1816                                 ast_cli(a->fd, "admin_toggle_mute_participants");
1817                                 break;
1818                         case MENU_ACTION_PARTICIPANT_COUNT:
1819                                 ast_cli(a->fd, "participant_count");
1820                                 break;
1821                         case MENU_ACTION_ADMIN_KICK_LAST:
1822                                 ast_cli(a->fd, "admin_kick_last");
1823                                 break;
1824                         case MENU_ACTION_LEAVE:
1825                                 ast_cli(a->fd, "leave_conference");
1826                                 break;
1827                         case MENU_ACTION_SET_SINGLE_VIDEO_SRC:
1828                                 ast_cli(a->fd, "set_as_single_video_src");
1829                                 break;
1830                         case MENU_ACTION_RELEASE_SINGLE_VIDEO_SRC:
1831                                 ast_cli(a->fd, "release_as_single_video_src");
1832                                 break;
1833                         }
1834                         action_num++;
1835                 }
1836                 ast_cli(a->fd,"\n");
1837         }
1838
1839
1840         ao2_unlock(menu);
1841         return CLI_SUCCESS;
1842 }
1843
1844 static struct ast_cli_entry cli_confbridge_parser[] = {
1845         AST_CLI_DEFINE(handle_cli_confbridge_show_user_profile, "Show a conference user profile."),
1846         AST_CLI_DEFINE(handle_cli_confbridge_show_bridge_profile, "Show a conference bridge profile."),
1847         AST_CLI_DEFINE(handle_cli_confbridge_show_menu, "Show a conference menu"),
1848         AST_CLI_DEFINE(handle_cli_confbridge_show_user_profiles, "Show a list of conference user profiles."),
1849         AST_CLI_DEFINE(handle_cli_confbridge_show_bridge_profiles, "Show a list of conference bridge profiles."),
1850         AST_CLI_DEFINE(handle_cli_confbridge_show_menus, "Show a list of conference menus"),
1851
1852 };
1853
1854 static void confbridge_cfg_destructor(void *obj)
1855 {
1856         struct confbridge_cfg *cfg = obj;
1857         ao2_cleanup(cfg->user_profiles);
1858         ao2_cleanup(cfg->bridge_profiles);
1859         ao2_cleanup(cfg->menus);
1860 }
1861
1862 void *confbridge_cfg_alloc(void)
1863 {
1864         struct confbridge_cfg *cfg;
1865
1866         if (!(cfg = ao2_alloc(sizeof(*cfg), confbridge_cfg_destructor))) {
1867                 return NULL;
1868         }
1869
1870         if (!(cfg->user_profiles = ao2_container_alloc(283, user_hash_cb, user_cmp_cb))) {
1871                 goto error;
1872         }
1873
1874         if (!(cfg->bridge_profiles = ao2_container_alloc(283, bridge_hash_cb, bridge_cmp_cb))) {
1875                 goto error;
1876         }
1877
1878         if (!(cfg->menus = ao2_container_alloc(283, menu_hash_cb, menu_cmp_cb))) {
1879                 goto error;
1880         }
1881
1882         return cfg;
1883 error:
1884         ao2_ref(cfg, -1);
1885         return NULL;
1886 }
1887
1888 static int announce_user_count_all_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
1889 {
1890         struct user_profile *u_profile = obj;
1891
1892         if (strcasecmp(var->name, "announce_user_count_all")) {
1893                 return -1;
1894         }
1895         if (ast_true(var->value)) {
1896                 u_profile->flags = u_profile->flags | USER_OPT_ANNOUNCEUSERCOUNTALL;
1897         } else if (ast_false(var->value)) {
1898                 u_profile->flags = u_profile->flags & ~USER_OPT_ANNOUNCEUSERCOUNTALL;
1899         } else if (sscanf(var->value, "%30u", &u_profile->announce_user_count_all_after) == 1) {
1900                 u_profile->flags = u_profile->flags | USER_OPT_ANNOUNCEUSERCOUNTALL;
1901         } else {
1902                 return -1;
1903         }
1904         return 0;
1905 }
1906
1907 static int mix_interval_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
1908 {
1909         struct bridge_profile *b_profile = obj;
1910
1911         if (strcasecmp(var->name, "mixing_interval")) {
1912                 return -1;
1913         }
1914         if (sscanf(var->value, "%30u", &b_profile->mix_interval) != 1) {
1915                 return -1;
1916         }
1917         switch (b_profile->mix_interval) {
1918         case 10:
1919         case 20:
1920         case 40:
1921         case 80:
1922                 return 0;
1923         default:
1924                 return -1;
1925         }
1926 }
1927
1928 static int video_mode_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
1929 {
1930         struct bridge_profile *b_profile = obj;
1931
1932         if (strcasecmp(var->name, "video_mode")) {
1933                 return -1;
1934         }
1935         if (!strcasecmp(var->value, "first_marked")) {
1936                 ast_set_flags_to(b_profile,
1937                         BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED
1938                                 | BRIDGE_OPT_VIDEO_SRC_LAST_MARKED
1939                                 | BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER,
1940                         BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED);
1941         } else if (!strcasecmp(var->value, "last_marked")) {
1942                 ast_set_flags_to(b_profile,
1943                         BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED
1944                                 | BRIDGE_OPT_VIDEO_SRC_LAST_MARKED
1945                                 | BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER,
1946                         BRIDGE_OPT_VIDEO_SRC_LAST_MARKED);
1947         } else if (!strcasecmp(var->value, "follow_talker")) {
1948                 ast_set_flags_to(b_profile,
1949                         BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED
1950                                 | BRIDGE_OPT_VIDEO_SRC_LAST_MARKED
1951                                 | BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER,
1952                         BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER);
1953         } else if (!strcasecmp(var->value, "none")) {
1954                 ast_clear_flag(b_profile,
1955                         BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED
1956                                 | BRIDGE_OPT_VIDEO_SRC_LAST_MARKED
1957                                 | BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER);
1958         } else {
1959                 return -1;
1960         }
1961         return 0;
1962 }
1963
1964 static int user_template_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
1965 {
1966         struct user_profile *u_profile = obj;
1967
1968         return conf_find_user_profile(NULL, var->value, u_profile) ? 0 : -1;
1969 }
1970
1971 static int bridge_template_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
1972 {
1973         struct bridge_profile *b_profile = obj;
1974         struct bridge_profile_sounds *sounds = bridge_profile_sounds_alloc();
1975         struct bridge_profile_sounds *oldsounds = b_profile->sounds;
1976
1977         if (!sounds) {
1978                 return -1;
1979         }
1980         if (!(conf_find_bridge_profile(NULL, var->value, b_profile))) {
1981                 ao2_ref(sounds, -1);
1982                 return -1;
1983         }
1984         /* Using a bridge profile as a template is a little complicated due to the sounds. Since the sounds
1985          * structure of a dynamic profile will need to be altered, a completely new sounds structure must be
1986          * created instead of simply holding a reference to the one built by the config file. */
1987         ast_string_field_set(sounds, onlyperson, b_profile->sounds->onlyperson);
1988         ast_string_field_set(sounds, onlyone, b_profile->sounds->onlyone);
1989         ast_string_field_set(sounds, hasjoin, b_profile->sounds->hasjoin);
1990         ast_string_field_set(sounds, hasleft, b_profile->sounds->hasleft);
1991         ast_string_field_set(sounds, kicked, b_profile->sounds->kicked);
1992         ast_string_field_set(sounds, muted, b_profile->sounds->muted);
1993         ast_string_field_set(sounds, unmuted, b_profile->sounds->unmuted);
1994         ast_string_field_set(sounds, thereare, b_profile->sounds->thereare);
1995         ast_string_field_set(sounds, otherinparty, b_profile->sounds->otherinparty);
1996         ast_string_field_set(sounds, placeintoconf, b_profile->sounds->placeintoconf);
1997         ast_string_field_set(sounds, waitforleader, b_profile->sounds->waitforleader);
1998         ast_string_field_set(sounds, leaderhasleft, b_profile->sounds->leaderhasleft);
1999         ast_string_field_set(sounds, getpin, b_profile->sounds->getpin);
2000         ast_string_field_set(sounds, invalidpin, b_profile->sounds->invalidpin);
2001         ast_string_field_set(sounds, locked, b_profile->sounds->locked);
2002         ast_string_field_set(sounds, unlockednow, b_profile->sounds->unlockednow);
2003         ast_string_field_set(sounds, lockednow, b_profile->sounds->lockednow);
2004         ast_string_field_set(sounds, errormenu, b_profile->sounds->errormenu);
2005         ast_string_field_set(sounds, join, b_profile->sounds->join);
2006         ast_string_field_set(sounds, leave, b_profile->sounds->leave);
2007         ast_string_field_set(sounds, participantsmuted, b_profile->sounds->participantsmuted);
2008         ast_string_field_set(sounds, participantsunmuted, b_profile->sounds->participantsunmuted);
2009         ast_string_field_set(sounds, begin, b_profile->sounds->begin);
2010
2011         ao2_ref(b_profile->sounds, -1); /* sounds struct copied over to it from the template by reference only. */
2012         ao2_ref(oldsounds, -1);    /* original sounds struct we don't need anymore */
2013         b_profile->sounds = sounds;     /* the new sounds struct that is a deep copy of the one from the template. */
2014
2015         return 0;
2016 }
2017
2018 static int copy_menu_entry(struct conf_menu_entry *dst, struct conf_menu_entry *src)
2019 {
2020         struct conf_menu_action *menu_action;
2021         struct conf_menu_action *new_menu_action;
2022
2023         ast_copy_string(dst->dtmf, src->dtmf, sizeof(dst->dtmf));
2024         AST_LIST_HEAD_INIT_NOLOCK(&dst->actions);
2025
2026         AST_LIST_TRAVERSE(&src->actions, menu_action, action) {
2027                 if (!(new_menu_action = ast_calloc(1, sizeof(*new_menu_action)))) {
2028                         return -1;
2029                 }
2030                 memcpy(new_menu_action, menu_action, sizeof(*new_menu_action));
2031                 AST_LIST_NEXT(new_menu_action, action) = NULL;
2032                 AST_LIST_INSERT_TAIL(&dst->actions, new_menu_action, action);
2033         }
2034
2035         return 0;
2036 }
2037
2038 static int conf_menu_profile_copy(struct conf_menu *dst, struct conf_menu *src)
2039 {
2040         /* Copy each menu item to the dst struct */
2041         struct conf_menu_entry *cur;
2042
2043         AST_LIST_TRAVERSE(&src->entries, cur, entry) {
2044                 struct conf_menu_entry *cpy;
2045
2046                 if (!(cpy = ast_calloc(1, sizeof(*cpy)))) {
2047                         return -1;
2048                 }
2049
2050                 if (copy_menu_entry(cpy, cur)) {
2051                         conf_menu_entry_destroy(cpy);
2052                         ast_free(cpy);
2053                         return -1;
2054                 }
2055                 AST_LIST_INSERT_TAIL(&dst->entries, cpy, entry);
2056         }
2057
2058         return 0;
2059 }
2060
2061 static int menu_template_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
2062 {
2063         struct conf_menu *dst_menu = obj;
2064         struct confbridge_cfg *cfg = aco_pending_config(&cfg_info);
2065         RAII_VAR(struct conf_menu *, src_menu, NULL, ao2_cleanup);
2066
2067         if (!cfg) {
2068                 return 0;
2069         }
2070
2071         if (!(src_menu = ao2_find(cfg->menus, var->value, OBJ_KEY))) {
2072                 return -1;
2073         }
2074
2075         if (conf_menu_profile_copy(dst_menu, src_menu)) {
2076                 return -1;
2077         }
2078
2079         return 0;
2080 }
2081
2082 static int sound_option_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
2083 {
2084         set_sound(var->name, var->value, obj);
2085         return 0;
2086 }
2087
2088 static int menu_option_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
2089 {
2090         add_menu_entry(obj, var->name, var->value);
2091         return 0;
2092 }
2093
2094 static int verify_default_profiles(void)
2095 {
2096         RAII_VAR(struct user_profile *, user_profile, NULL, ao2_cleanup);
2097         RAII_VAR(struct bridge_profile *, bridge_profile, NULL, ao2_cleanup);
2098         RAII_VAR(struct conf_menu *, menu_profile, NULL, ao2_cleanup);
2099         struct confbridge_cfg *cfg = aco_pending_config(&cfg_info);
2100
2101         if (!cfg) {
2102                 return 0;
2103         }
2104
2105         bridge_profile = ao2_find(cfg->bridge_profiles, DEFAULT_BRIDGE_PROFILE, OBJ_KEY);
2106         if (!bridge_profile) {
2107                 bridge_profile = bridge_profile_alloc(DEFAULT_BRIDGE_PROFILE);
2108                 if (!bridge_profile) {
2109                         return -1;
2110                 }
2111                 ast_log(AST_LOG_NOTICE, "Adding %s profile to app_confbridge\n", DEFAULT_BRIDGE_PROFILE);
2112                 aco_set_defaults(&bridge_type, DEFAULT_BRIDGE_PROFILE, bridge_profile);
2113                 ao2_link(cfg->bridge_profiles, bridge_profile);
2114         }
2115
2116         user_profile = ao2_find(cfg->user_profiles, DEFAULT_USER_PROFILE, OBJ_KEY);
2117         if (!user_profile) {
2118                 user_profile = user_profile_alloc(DEFAULT_USER_PROFILE);
2119                 if (!user_profile) {
2120                         return -1;
2121                 }
2122                 ast_log(AST_LOG_NOTICE, "Adding %s profile to app_confbridge\n", DEFAULT_USER_PROFILE);
2123                 aco_set_defaults(&user_type, DEFAULT_USER_PROFILE, user_profile);
2124                 ao2_link(cfg->user_profiles, user_profile);
2125         }
2126
2127         menu_profile = ao2_find(cfg->menus, DEFAULT_MENU_PROFILE, OBJ_KEY);
2128         if (!menu_profile) {
2129                 menu_profile = menu_alloc(DEFAULT_MENU_PROFILE);
2130                 if (!menu_profile) {
2131                         return -1;
2132                 }
2133                 ast_log(AST_LOG_NOTICE, "Adding %s menu to app_confbridge\n", DEFAULT_MENU_PROFILE);
2134                 aco_set_defaults(&menu_type, DEFAULT_MENU_PROFILE, menu_profile);
2135                 ao2_link(cfg->menus, menu_profile);
2136         }
2137
2138         return 0;
2139 }
2140
2141 int conf_load_config(void)
2142 {
2143         if (aco_info_init(&cfg_info)) {
2144                 return -1;
2145         }
2146
2147         /* User options */
2148         aco_option_register(&cfg_info, "type", ACO_EXACT, user_types, NULL, OPT_NOOP_T, 0, 0);
2149         aco_option_register(&cfg_info, "admin", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_ADMIN);
2150         aco_option_register(&cfg_info, "marked", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_MARKEDUSER);
2151         aco_option_register(&cfg_info, "startmuted", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_STARTMUTED);
2152         aco_option_register(&cfg_info, "music_on_hold_when_empty", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_MUSICONHOLD);
2153         aco_option_register(&cfg_info, "quiet", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_QUIET);
2154         aco_option_register_custom(&cfg_info, "announce_user_count_all", ACO_EXACT, user_types, "no", announce_user_count_all_handler, 0);
2155         aco_option_register(&cfg_info, "announce_user_count", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_ANNOUNCEUSERCOUNT);
2156         /* Negative logic. Defaults to "yes" and evaluates with ast_false(). If !ast_false(), USER_OPT_NOONLYPERSON is cleared */
2157         aco_option_register(&cfg_info, "announce_only_user", ACO_EXACT, user_types, "yes", OPT_BOOLFLAG_T, 0, FLDSET(struct user_profile, flags), USER_OPT_NOONLYPERSON);
2158         aco_option_register(&cfg_info, "wait_marked", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_WAITMARKED);
2159         aco_option_register(&cfg_info, "end_marked", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_ENDMARKED);
2160         aco_option_register(&cfg_info, "talk_detection_events", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_TALKER_DETECT);
2161         aco_option_register(&cfg_info, "dtmf_passthrough", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_DTMF_PASS);
2162         aco_option_register(&cfg_info, "announce_join_leave", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_ANNOUNCE_JOIN_LEAVE);
2163         aco_option_register(&cfg_info, "announce_join_leave_review", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_ANNOUNCE_JOIN_LEAVE_REVIEW);
2164         aco_option_register(&cfg_info, "pin", ACO_EXACT, user_types, NULL, OPT_CHAR_ARRAY_T, 0, CHARFLDSET(struct user_profile, pin));
2165         aco_option_register(&cfg_info, "music_on_hold_class", ACO_EXACT, user_types, NULL, OPT_CHAR_ARRAY_T, 0, CHARFLDSET(struct user_profile, moh_class));
2166         aco_option_register(&cfg_info, "announcement", ACO_EXACT, user_types, NULL, OPT_CHAR_ARRAY_T, 0, CHARFLDSET(struct user_profile, announcement));
2167         aco_option_register(&cfg_info, "denoise", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_DENOISE);
2168         aco_option_register(&cfg_info, "dsp_drop_silence", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_DROP_SILENCE);
2169         aco_option_register(&cfg_info, "dsp_silence_threshold", ACO_EXACT, user_types, __stringify(DEFAULT_SILENCE_THRESHOLD), OPT_UINT_T, 0, FLDSET(struct user_profile, silence_threshold));
2170         aco_option_register(&cfg_info, "dsp_talking_threshold", ACO_EXACT, user_types, __stringify(DEFAULT_TALKING_THRESHOLD), OPT_UINT_T, 0, FLDSET(struct user_profile, talking_threshold));
2171         aco_option_register(&cfg_info, "jitterbuffer", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_JITTERBUFFER);
2172         aco_option_register(&cfg_info, "timeout", ACO_EXACT, user_types, "0", OPT_UINT_T, 0, FLDSET(struct user_profile, timeout));
2173         /* This option should only be used with the CONFBRIDGE dialplan function */
2174         aco_option_register_custom(&cfg_info, "template", ACO_EXACT, user_types, NULL, user_template_handler, 0);
2175
2176 /* XXX ASTERISK-21271 need a user supplied bridge merge_priority to merge ConfBridges (default = 1, range 1-INT_MAX) */
2177         /* Bridge options */
2178         aco_option_register(&cfg_info, "type", ACO_EXACT, bridge_types, NULL, OPT_NOOP_T, 0, 0);
2179         aco_option_register(&cfg_info, "jitterbuffer", ACO_EXACT, bridge_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct bridge_profile, flags), USER_OPT_JITTERBUFFER);
2180         /* "auto" will fail to parse as a uint, but we use PARSE_DEFAULT to set the value to 0 in that case, which is the value that auto resolves to */
2181         aco_option_register(&cfg_info, "internal_sample_rate", ACO_EXACT, bridge_types, "0", OPT_UINT_T, PARSE_DEFAULT, FLDSET(struct bridge_profile, internal_sample_rate), 0);
2182         aco_option_register(&cfg_info, "binaural_active", ACO_EXACT, bridge_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct bridge_profile, flags), BRIDGE_OPT_BINAURAL_ACTIVE);
2183         aco_option_register_custom(&cfg_info, "mixing_interval", ACO_EXACT, bridge_types, "20", mix_interval_handler, 0);
2184         aco_option_register(&cfg_info, "record_conference", ACO_EXACT, bridge_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct bridge_profile, flags), BRIDGE_OPT_RECORD_CONFERENCE);
2185         aco_option_register_custom(&cfg_info, "video_mode", ACO_EXACT, bridge_types, NULL, video_mode_handler, 0);
2186         aco_option_register(&cfg_info, "record_file_append", ACO_EXACT, bridge_types, "yes", OPT_BOOLFLAG_T, 1, FLDSET(struct bridge_profile, flags), BRIDGE_OPT_RECORD_FILE_APPEND);
2187         aco_option_register(&cfg_info, "record_file_timestamp", ACO_EXACT, bridge_types, "yes", OPT_BOOLFLAG_T, 1, FLDSET(struct bridge_profile, flags), BRIDGE_OPT_RECORD_FILE_TIMESTAMP);
2188         aco_option_register(&cfg_info, "max_members", ACO_EXACT, bridge_types, "0", OPT_UINT_T, 0, FLDSET(struct bridge_profile, max_members));
2189         aco_option_register(&cfg_info, "record_file", ACO_EXACT, bridge_types, NULL, OPT_CHAR_ARRAY_T, 0, CHARFLDSET(struct bridge_profile, rec_file));
2190         aco_option_register(&cfg_info, "record_options", ACO_EXACT, bridge_types, NULL, OPT_CHAR_ARRAY_T, 0, CHARFLDSET(struct bridge_profile, rec_options));
2191         aco_option_register(&cfg_info, "record_command", ACO_EXACT, bridge_types, NULL, OPT_CHAR_ARRAY_T, 0, CHARFLDSET(struct bridge_profile, rec_command));
2192         aco_option_register(&cfg_info, "regcontext", ACO_EXACT, bridge_types, NULL, OPT_CHAR_ARRAY_T, 0, CHARFLDSET(struct bridge_profile, regcontext));
2193         aco_option_register(&cfg_info, "language", ACO_EXACT, bridge_types, "en", OPT_CHAR_ARRAY_T, 0, CHARFLDSET(struct bridge_profile, language));
2194         aco_option_register_custom(&cfg_info, "^sound_", ACO_REGEX, bridge_types, NULL, sound_option_handler, 0);
2195         /* This option should only be used with the CONFBRIDGE dialplan function */
2196         aco_option_register_custom(&cfg_info, "template", ACO_EXACT, bridge_types, NULL, bridge_template_handler, 0);
2197
2198         /* Menu options */
2199         aco_option_register(&cfg_info, "type", ACO_EXACT, menu_types, NULL, OPT_NOOP_T, 0, 0);
2200         aco_option_register_custom(&cfg_info, "template", ACO_EXACT, menu_types, NULL, menu_template_handler, 0);
2201         aco_option_register_custom(&cfg_info, "^[0-9A-D*#]+$", ACO_REGEX, menu_types, NULL, menu_option_handler, 0);
2202
2203         if (aco_process_config(&cfg_info, 0) == ACO_PROCESS_ERROR) {
2204                 goto error;
2205         }
2206
2207         if (ast_cli_register_multiple(cli_confbridge_parser, ARRAY_LEN(cli_confbridge_parser))) {
2208                 goto error;
2209         }
2210
2211         return 0;
2212 error:
2213         conf_destroy_config();
2214         return -1;
2215 }
2216
2217 int conf_reload_config(void)
2218 {
2219         if (aco_process_config(&cfg_info, 1) == ACO_PROCESS_ERROR) {
2220                 /* On a reload, just keep the config we already have in place. */
2221                 return -1;
2222         }
2223         return 0;
2224 }
2225
2226 static void conf_user_profile_copy(struct user_profile *dst, struct user_profile *src)
2227 {
2228         *dst = *src;
2229 }
2230
2231 const struct user_profile *conf_find_user_profile(struct ast_channel *chan, const char *user_profile_name, struct user_profile *result)
2232 {
2233         struct user_profile *tmp2;
2234         struct ast_datastore *datastore = NULL;
2235         struct func_confbridge_data *b_data = NULL;
2236         RAII_VAR(struct confbridge_cfg *, cfg, ao2_global_obj_ref(cfg_handle), ao2_cleanup);
2237
2238         if (chan && ast_strlen_zero(user_profile_name)) {
2239                 ast_channel_lock(chan);
2240                 datastore = ast_channel_datastore_find(chan, &confbridge_datastore, NULL);
2241                 ast_channel_unlock(chan);
2242                 if (datastore) {
2243                         b_data = datastore->data;
2244                         if (b_data->u_usable) {
2245                                 conf_user_profile_copy(result, &b_data->u_profile);
2246                                 return result;
2247                         }
2248                 }
2249         }
2250
2251         if (!cfg) {
2252                 return NULL;
2253         }
2254         if (ast_strlen_zero(user_profile_name)) {
2255                 user_profile_name = DEFAULT_USER_PROFILE;
2256         }
2257         if (!(tmp2 = ao2_find(cfg->user_profiles, user_profile_name, OBJ_KEY))) {
2258                 return NULL;
2259         }
2260         ao2_lock(tmp2);
2261         conf_user_profile_copy(result, tmp2);
2262         ao2_unlock(tmp2);
2263         ao2_ref(tmp2, -1);
2264
2265         return result;
2266 }
2267
2268 void conf_bridge_profile_copy(struct bridge_profile *dst, struct bridge_profile *src)
2269 {
2270         *dst = *src;
2271         if (src->sounds) {
2272                 ao2_ref(src->sounds, +1);
2273         }
2274 }
2275
2276 void conf_bridge_profile_destroy(struct bridge_profile *b_profile)
2277 {
2278         if (b_profile->sounds) {
2279                 ao2_ref(b_profile->sounds, -1);
2280                 b_profile->sounds = NULL;
2281         }
2282 }
2283
2284 const struct bridge_profile *conf_find_bridge_profile(struct ast_channel *chan, const char *bridge_profile_name, struct bridge_profile *result)
2285 {
2286         struct bridge_profile *tmp2;
2287         struct ast_datastore *datastore = NULL;
2288         struct func_confbridge_data *b_data = NULL;
2289         RAII_VAR(struct confbridge_cfg *, cfg, ao2_global_obj_ref(cfg_handle), ao2_cleanup);
2290
2291         if (chan && ast_strlen_zero(bridge_profile_name)) {
2292                 ast_channel_lock(chan);
2293                 datastore = ast_channel_datastore_find(chan, &confbridge_datastore, NULL);
2294                 ast_channel_unlock(chan);
2295                 if (datastore) {
2296                         b_data = datastore->data;
2297                         if (b_data->b_usable) {
2298                                 conf_bridge_profile_copy(result, &b_data->b_profile);
2299                                 return result;
2300                         }
2301                 }
2302         }
2303
2304         if (!cfg) {
2305                 return NULL;
2306         }
2307         if (ast_strlen_zero(bridge_profile_name)) {
2308                 bridge_profile_name = DEFAULT_BRIDGE_PROFILE;
2309         }
2310         if (!(tmp2 = ao2_find(cfg->bridge_profiles, bridge_profile_name, OBJ_KEY))) {
2311                 return NULL;
2312         }
2313         ao2_lock(tmp2);
2314         conf_bridge_profile_copy(result, tmp2);
2315         ao2_unlock(tmp2);
2316         ao2_ref(tmp2, -1);
2317
2318         return result;
2319 }
2320
2321 struct dtmf_menu_hook_pvt {
2322         struct confbridge_user *user;
2323         struct conf_menu_entry menu_entry;
2324         struct conf_menu *menu;
2325 };
2326
2327 static void menu_hook_destroy(void *hook_pvt)
2328 {
2329         struct dtmf_menu_hook_pvt *pvt = hook_pvt;
2330         struct conf_menu_action *action = NULL;
2331
2332         ao2_cleanup(pvt->menu);
2333
2334         while ((action = AST_LIST_REMOVE_HEAD(&pvt->menu_entry.actions, action))) {
2335                 ast_free(action);
2336         }
2337         ast_free(pvt);
2338 }
2339
2340 static int menu_hook_callback(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
2341 {
2342         struct dtmf_menu_hook_pvt *pvt = hook_pvt;
2343
2344         return conf_handle_dtmf(bridge_channel, pvt->user, &pvt->menu_entry, pvt->menu);
2345 }
2346
2347 void conf_menu_entry_destroy(struct conf_menu_entry *menu_entry)
2348 {
2349         struct conf_menu_action *menu_action = NULL;
2350         while ((menu_action = AST_LIST_REMOVE_HEAD(&menu_entry->actions, action))) {
2351                 ast_free(menu_action);
2352         }
2353 }
2354
2355 int conf_find_menu_entry_by_sequence(const char *dtmf_sequence, struct conf_menu *menu, struct conf_menu_entry *result)
2356 {
2357         struct conf_menu_entry *menu_entry = NULL;
2358
2359         ao2_lock(menu);
2360         AST_LIST_TRAVERSE(&menu->entries, menu_entry, entry) {
2361                 if (!strcasecmp(menu_entry->dtmf, dtmf_sequence)) {
2362                         copy_menu_entry(result, menu_entry);
2363                         ao2_unlock(menu);
2364                         return 1;
2365                 }
2366         }
2367         ao2_unlock(menu);
2368
2369         return 0;
2370 }
2371
2372 static int apply_menu_to_user(struct confbridge_user *user, struct conf_menu *menu)
2373 {
2374         struct conf_menu_entry *menu_entry;
2375
2376         SCOPED_AO2LOCK(menu_lock, menu);
2377         AST_LIST_TRAVERSE(&menu->entries, menu_entry, entry) {
2378                 struct dtmf_menu_hook_pvt *pvt;
2379
2380                 if (!(pvt = ast_calloc(1, sizeof(*pvt)))) {
2381                         return -1;
2382                 }
2383                 pvt->user = user;
2384                 pvt->menu = ao2_bump(menu);
2385
2386                 if (copy_menu_entry(&pvt->menu_entry, menu_entry)) {
2387                         menu_hook_destroy(pvt);
2388                         return -1;
2389                 }
2390
2391                 if (ast_bridge_dtmf_hook(&user->features, pvt->menu_entry.dtmf,
2392                         menu_hook_callback, pvt, menu_hook_destroy, 0)) {
2393                         menu_hook_destroy(pvt);
2394                 }
2395         }
2396         strcpy(user->menu_name, menu->name); /* Safe */
2397
2398         return 0;
2399 }
2400
2401 int conf_set_menu_to_user(struct ast_channel *chan, struct confbridge_user *user, const char *menu_profile_name)
2402 {
2403         RAII_VAR(struct confbridge_cfg *, cfg, ao2_global_obj_ref(cfg_handle), ao2_cleanup);
2404         RAII_VAR(struct conf_menu *, menu, NULL, ao2_cleanup);
2405
2406         if (chan && ast_strlen_zero(menu_profile_name)) {
2407                 struct ast_datastore *datastore;
2408                 struct func_confbridge_data *b_data;
2409
2410                 ast_channel_lock(chan);
2411                 datastore = ast_channel_datastore_find(chan, &confbridge_datastore, NULL);
2412                 ast_channel_unlock(chan);
2413                 if (datastore) {
2414                         /* If a menu exists in the CONFBRIDGE function datastore, use it. */
2415                         b_data = datastore->data;
2416                         if (b_data->m_usable) {
2417                                 menu = ao2_bump(b_data->menu);
2418                                 return apply_menu_to_user(user, menu);
2419                         }
2420                 }
2421         }
2422
2423         /* Otherwise, we need to get whatever menu profile is specified to use (or default). */
2424         if (!cfg) {
2425                 return -1;
2426         }
2427
2428         if (ast_strlen_zero(menu_profile_name)) {
2429                 menu_profile_name = DEFAULT_MENU_PROFILE;
2430         }
2431
2432         if (!(menu = ao2_find(cfg->menus, menu_profile_name, OBJ_KEY))) {
2433                 return -1;
2434         }
2435
2436         return apply_menu_to_user(user, menu);
2437 }
2438
2439 void conf_destroy_config(void)
2440 {
2441         ast_cli_unregister_multiple(cli_confbridge_parser, ARRAY_LEN(cli_confbridge_parser));
2442         aco_info_destroy(&cfg_info);
2443         ao2_global_obj_release(cfg_handle);
2444 }