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