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