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