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