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