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