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