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