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