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