36f5c77273fa3573981400e0f3bdd1845ef6e998
[asterisk/asterisk.git] / apps / app_meetme.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2007, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * SLA Implementation by:
9  * Russell Bryant <russell@digium.com>
10  *
11  * See http://www.asterisk.org for more information about
12  * the Asterisk project. Please do not directly contact
13  * any of the maintainers of this project for assistance;
14  * the project provides a web site, mailing lists and IRC
15  * channels for your use.
16  *
17  * This program is free software, distributed under the terms of
18  * the GNU General Public License Version 2. See the LICENSE file
19  * at the top of the source tree.
20  */
21
22 /*! \file
23  *
24  * \brief Meet me conference bridge and Shared Line Appearances
25  *
26  * \author Mark Spencer <markster@digium.com>
27  * \author (SLA) Russell Bryant <russell@digium.com>
28  * 
29  * \ingroup applications
30  */
31
32 /*! \li \ref app_meetme.c uses configuration file \ref meetme.conf
33  * \addtogroup configuration_file Configuration Files
34  */
35
36 /*! 
37  * \page meetme.conf meetme.conf
38  * \verbinclude meetme.conf.sample
39  */
40
41 /*** MODULEINFO
42         <depend>dahdi</depend>
43         <defaultenabled>no</defaultenabled>
44         <support_level>extended</support_level>
45         <replacement>app_confbridge</replacement>
46  ***/
47
48 #include "asterisk.h"
49
50 #include <dahdi/user.h>
51
52 #include "asterisk/lock.h"
53 #include "asterisk/file.h"
54 #include "asterisk/channel.h"
55 #include "asterisk/pbx.h"
56 #include "asterisk/module.h"
57 #include "asterisk/config.h"
58 #include "asterisk/app.h"
59 #include "asterisk/dsp.h"
60 #include "asterisk/musiconhold.h"
61 #include "asterisk/manager.h"
62 #include "asterisk/cli.h"
63 #include "asterisk/say.h"
64 #include "asterisk/utils.h"
65 #include "asterisk/translate.h"
66 #include "asterisk/ulaw.h"
67 #include "asterisk/astobj2.h"
68 #include "asterisk/devicestate.h"
69 #include "asterisk/dial.h"
70 #include "asterisk/causes.h"
71 #include "asterisk/paths.h"
72 #include "asterisk/data.h"
73 #include "asterisk/test.h"
74 #include "asterisk/stasis.h"
75 #include "asterisk/stasis_channels.h"
76 #include "asterisk/stasis_message_router.h"
77 #include "asterisk/json.h"
78 #include "asterisk/format_compatibility.h"
79
80 #include "enter.h"
81 #include "leave.h"
82
83 /*** DOCUMENTATION
84         <application name="MeetMe" language="en_US">
85                 <synopsis>
86                         MeetMe conference bridge.
87                 </synopsis>
88                 <syntax>
89                         <parameter name="confno">
90                                 <para>The conference number</para>
91                         </parameter>
92                         <parameter name="options">
93                                 <optionlist>
94                                         <option name="a">
95                                                 <para>Set admin mode.</para>
96                                         </option>
97                                         <option name="A">
98                                                 <para>Set marked mode.</para>
99                                         </option>
100                                         <option name="b">
101                                                 <para>Run AGI script specified in <variable>MEETME_AGI_BACKGROUND</variable>
102                                                 Default: <literal>conf-background.agi</literal>.</para>
103                                                 <note><para>This does not work with non-DAHDI channels in the same
104                                                 conference).</para></note>
105                                         </option>
106                                         <option name="c">
107                                                 <para>Announce user(s) count on joining a conference.</para>
108                                         </option>
109                                         <option name="C">
110                                                 <para>Continue in dialplan when kicked out of conference.</para>
111                                         </option>
112                                         <option name="d">
113                                                 <para>Dynamically add conference.</para>
114                                         </option>
115                                         <option name="D">
116                                                 <para>Dynamically add conference, prompting for a PIN.</para>
117                                         </option>
118                                         <option name="e">
119                                                 <para>Select an empty conference.</para>
120                                         </option>
121                                         <option name="E">
122                                                 <para>Select an empty pinless conference.</para>
123                                         </option>
124                                         <option name="F">
125                                                 <para>Pass DTMF through the conference.</para>
126                                         </option>
127                                         <option name="G">
128                                                 <argument name="x" required="true">
129                                                         <para>The file to playback</para>
130                                                 </argument>
131                                                 <para>Play an intro announcement in conference.</para>
132                                         </option>
133                                         <option name="i">
134                                                 <para>Announce user join/leave with review.</para>
135                                         </option>
136                                         <option name="I">
137                                                 <para>Announce user join/leave without review.</para>
138                                         </option>
139                                         <option name="k">
140                                                 <para>Close the conference if there's only one active participant left at exit.</para>
141                                         </option>
142                                         <option name="l">
143                                                 <para>Set listen only mode (Listen only, no talking).</para>
144                                         </option>
145                                         <option name="m">
146                                                 <para>Set initially muted.</para>
147                                         </option>
148                                         <option name="M" hasparams="optional">
149                                                 <para>Enable music on hold when the conference has a single caller. Optionally,
150                                                 specify a musiconhold class to use. If one is not provided, it will use the
151                                                 channel's currently set music class, or <literal>default</literal>.</para>
152                                                 <argument name="class" required="true" />
153                                         </option>
154                                         <option name="n">
155                                                 <para>Disable the denoiser. By default, if <literal>func_speex</literal> is loaded, Asterisk
156                                                 will apply a denoiser to channels in the MeetMe conference. However, channel
157                                                 drivers that present audio with a varying rate will experience degraded
158                                                 performance with a denoiser attached. This parameter allows a channel joining
159                                                 the conference to choose not to have a denoiser attached without having to
160                                                 unload <literal>func_speex</literal>.</para>
161                                         </option>
162                                         <option name="o">
163                                                 <para>Set talker optimization - treats talkers who aren't speaking as
164                                                 being muted, meaning (a) No encode is done on transmission and (b)
165                                                 Received audio that is not registered as talking is omitted causing no
166                                                 buildup in background noise.</para>
167                                         </option>
168                                         <option name="p" hasparams="optional">
169                                                 <para>Allow user to exit the conference by pressing <literal>#</literal> (default)
170                                                 or any of the defined keys. Dial plan execution will continue at the next
171                                                 priority following MeetMe. The key used is set to channel variable
172                                                 <variable>MEETME_EXIT_KEY</variable>.</para>
173                                                 <argument name="keys" required="true" />
174                                                 <note>
175                                                         <para>Option <literal>s</literal> has priority for <literal>*</literal>
176                                                         since it cannot change its activation code.</para>
177                                                 </note>
178                                         </option>
179                                         <option name="P">
180                                                 <para>Always prompt for the pin even if it is specified.</para>
181                                         </option>
182                                         <option name="q">
183                                                 <para>Quiet mode (don't play enter/leave sounds).</para>
184                                         </option>
185                                         <option name="r">
186                                                 <para>Record conference (records as <variable>MEETME_RECORDINGFILE</variable>
187                                                 using format <variable>MEETME_RECORDINGFORMAT</variable>. Default filename is
188                                                 <literal>meetme-conf-rec-${CONFNO}-${UNIQUEID}</literal> and the default format is
189                                                 wav.</para>
190                                         </option>
191                                         <option name="s">
192                                                 <para>Present menu (user or admin) when <literal>*</literal> is received
193                                                 (send to menu).</para>
194                                         </option>
195                                         <option name="t">
196                                                 <para>Set talk only mode. (Talk only, no listening).</para>
197                                         </option>
198                                         <option name="T">
199                                                 <para>Set talker detection (sent to manager interface and meetme list).</para>
200                                         </option>
201                                         <option name="v" hasparams="optional">
202                                                 <para>Announce when a user is joining or leaving the conference.  Use the voicemail greeting as the announcement.
203                                                  If the i or I options are set, the application will fall back to them if no voicemail greeting can be found.</para>
204                                                 <argument name="mailbox@[context]" required="true">
205                                                         <para>The mailbox and voicemail context to play from.  If no context provided, assumed context is default.</para>
206                                                 </argument>
207                                         </option>
208                                         <option name="w" hasparams="optional">
209                                                 <para>Wait until the marked user enters the conference.</para>
210                                                 <argument name="secs" required="true" />
211                                         </option>
212                                         <option name="x">
213                                                 <para>Leave the conference when the last marked user leaves.</para>
214                                         </option>
215                                         <option name="X">
216                                                 <para>Allow user to exit the conference by entering a valid single digit
217                                                 extension <variable>MEETME_EXIT_CONTEXT</variable> or the current context
218                                                 if that variable is not defined.</para>
219                                                 <note>
220                                                         <para>Option <literal>s</literal> has priority for <literal>*</literal>
221                                                         since it cannot change its activation code.</para>
222                                                 </note>
223                                         </option>
224                                         <option name="1">
225                                                 <para>Do not play message when first person enters</para>
226                                         </option>
227                                         <option name="S">
228                                                 <para>Kick the user <replaceable>x</replaceable> seconds <emphasis>after</emphasis> he entered into
229                                                 the conference.</para>
230                                                 <argument name="x" required="true" />
231                                         </option>
232                                         <option name="L" argsep=":">
233                                                 <para>Limit the conference to <replaceable>x</replaceable> ms. Play a warning when
234                                                 <replaceable>y</replaceable> ms are left. Repeat the warning every <replaceable>z</replaceable> ms.
235                                                 The following special variables can be used with this option:</para>
236                                                 <variablelist>
237                                                         <variable name="CONF_LIMIT_TIMEOUT_FILE">
238                                                                 <para>File to play when time is up.</para>
239                                                         </variable>
240                                                         <variable name="CONF_LIMIT_WARNING_FILE">
241                                                                 <para>File to play as warning if <replaceable>y</replaceable> is defined. The
242                                                                 default is to say the time remaining.</para>
243                                                         </variable>
244                                                 </variablelist>
245                                                 <argument name="x" />
246                                                 <argument name="y" />
247                                                 <argument name="z" />
248                                         </option>
249                                 </optionlist>
250                         </parameter>
251                         <parameter name="pin" />
252                 </syntax>
253                 <description>
254                         <para>Enters the user into a specified MeetMe conference.  If the <replaceable>confno</replaceable>
255                         is omitted, the user will be prompted to enter one.  User can exit the conference by hangup, or
256                         if the <literal>p</literal> option is specified, by pressing <literal>#</literal>.</para>
257                         <note><para>The DAHDI kernel modules and a functional DAHDI timing source (see dahdi_test)
258                         must be present for conferencing to operate properly. In addition, the chan_dahdi channel driver
259                         must be loaded for the <literal>i</literal> and <literal>r</literal> options to operate at
260                         all.</para></note>
261                 </description>
262                 <see-also>
263                         <ref type="application">MeetMeCount</ref>
264                         <ref type="application">MeetMeAdmin</ref>
265                         <ref type="application">MeetMeChannelAdmin</ref>
266                 </see-also>
267         </application>
268         <application name="MeetMeCount" language="en_US">
269                 <synopsis>
270                         MeetMe participant count.
271                 </synopsis>
272                 <syntax>
273                         <parameter name="confno" required="true">
274                                 <para>Conference number.</para>
275                         </parameter>
276                         <parameter name="var" />
277                 </syntax>
278                 <description>
279                         <para>Plays back the number of users in the specified MeetMe conference.
280                         If <replaceable>var</replaceable> is specified, playback will be skipped and the value
281                         will be returned in the variable. Upon application completion, MeetMeCount will hangup
282                         the channel, unless priority <literal>n+1</literal> exists, in which case priority progress will
283                         continue.</para>
284                 </description>
285                 <see-also>
286                         <ref type="application">MeetMe</ref>
287                 </see-also>
288         </application>
289         <application name="MeetMeAdmin" language="en_US">
290                 <synopsis>
291                         MeetMe conference administration.
292                 </synopsis>
293                 <syntax>
294                         <parameter name="confno" required="true" />
295                         <parameter name="command" required="true">
296                                 <optionlist>
297                                         <option name="e">
298                                                 <para>Eject last user that joined.</para>
299                                         </option>
300                                         <option name="E">
301                                                 <para>Extend conference end time, if scheduled.</para>
302                                         </option>
303                                         <option name="k">
304                                                 <para>Kick one user out of conference.</para>
305                                         </option>
306                                         <option name="K">
307                                                 <para>Kick all users out of conference.</para>
308                                         </option>
309                                         <option name="l">
310                                                 <para>Unlock conference.</para>
311                                         </option>
312                                         <option name="L">
313                                                 <para>Lock conference.</para>
314                                         </option>
315                                         <option name="m">
316                                                 <para>Unmute one user.</para>
317                                         </option>
318                                         <option name="M">
319                                                 <para>Mute one user.</para>
320                                         </option>
321                                         <option name="n">
322                                                 <para>Unmute all users in the conference.</para>
323                                         </option>
324                                         <option name="N">
325                                                 <para>Mute all non-admin users in the conference.</para>
326                                         </option>
327                                         <option name="r">
328                                                 <para>Reset one user's volume settings.</para>
329                                         </option>
330                                         <option name="R">
331                                                 <para>Reset all users volume settings.</para>
332                                         </option>
333                                         <option name="s">
334                                                 <para>Lower entire conference speaking volume.</para>
335                                         </option>
336                                         <option name="S">
337                                                 <para>Raise entire conference speaking volume.</para>
338                                         </option>
339                                         <option name="t">
340                                                 <para>Lower one user's talk volume.</para>
341                                         </option>
342                                         <option name="T">
343                                                 <para>Raise one user's talk volume.</para>
344                                         </option>
345                                         <option name="u">
346                                                 <para>Lower one user's listen volume.</para>
347                                         </option>
348                                         <option name="U">
349                                                 <para>Raise one user's listen volume.</para>
350                                         </option>
351                                         <option name="v">
352                                                 <para>Lower entire conference listening volume.</para>
353                                         </option>
354                                         <option name="V">
355                                                 <para>Raise entire conference listening volume.</para>
356                                         </option>
357                                 </optionlist>
358                         </parameter>
359                         <parameter name="user" />
360                 </syntax>
361                 <description>
362                         <para>Run admin <replaceable>command</replaceable> for conference <replaceable>confno</replaceable>.</para>
363                         <para>Will additionally set the variable <variable>MEETMEADMINSTATUS</variable> with one of
364                         the following values:</para>
365                         <variablelist>
366                                 <variable name="MEETMEADMINSTATUS">
367                                         <value name="NOPARSE">
368                                                 Invalid arguments.
369                                         </value>
370                                         <value name="NOTFOUND">
371                                                 User specified was not found.
372                                         </value>
373                                         <value name="FAILED">
374                                                 Another failure occurred.
375                                         </value>
376                                         <value name="OK">
377                                                 The operation was completed successfully.
378                                         </value>
379                                 </variable>
380                         </variablelist>
381                 </description>
382                 <see-also>
383                         <ref type="application">MeetMe</ref>
384                 </see-also>
385         </application>
386         <application name="MeetMeChannelAdmin" language="en_US">
387                 <synopsis>
388                         MeetMe conference Administration (channel specific).
389                 </synopsis>
390                 <syntax>
391                         <parameter name="channel" required="true" />
392                         <parameter name="command" required="true">
393                                 <optionlist>
394                                         <option name="k">
395                                                 <para>Kick the specified user out of the conference he is in.</para>
396                                         </option>
397                                         <option name="m">
398                                                 <para>Unmute the specified user.</para>
399                                         </option>
400                                         <option name="M">
401                                                 <para>Mute the specified user.</para>
402                                         </option>
403                                 </optionlist>
404                         </parameter>
405                 </syntax>
406                 <description>
407                         <para>Run admin <replaceable>command</replaceable> for a specific
408                         <replaceable>channel</replaceable> in any conference.</para>
409                 </description>
410         </application>
411         <application name="SLAStation" language="en_US">
412                 <synopsis>
413                         Shared Line Appearance Station.
414                 </synopsis>
415                 <syntax>
416                         <parameter name="station" required="true">
417                                 <para>Station name</para>
418                         </parameter>
419                 </syntax>
420                 <description>
421                         <para>This application should be executed by an SLA station. The argument depends
422                         on how the call was initiated. If the phone was just taken off hook, then the argument
423                         <replaceable>station</replaceable> should be just the station name. If the call was
424                         initiated by pressing a line key, then the station name should be preceded by an underscore
425                         and the trunk name associated with that line button.</para>
426                         <para>For example: <literal>station1_line1</literal></para>
427                         <para>On exit, this application will set the variable <variable>SLASTATION_STATUS</variable> to
428                         one of the following values:</para>
429                         <variablelist>
430                                 <variable name="SLASTATION_STATUS">
431                                         <value name="FAILURE" />
432                                         <value name="CONGESTION" />
433                                         <value name="SUCCESS" />
434                                 </variable>
435                         </variablelist>
436                 </description>
437         </application>
438         <application name="SLATrunk" language="en_US">
439                 <synopsis>
440                         Shared Line Appearance Trunk.
441                 </synopsis>
442                 <syntax>
443                         <parameter name="trunk" required="true">
444                                 <para>Trunk name</para>
445                         </parameter>
446                         <parameter name="options">
447                                 <optionlist>
448                                         <option name="M" hasparams="optional">
449                                                 <para>Play back the specified MOH <replaceable>class</replaceable>
450                                                 instead of ringing</para>
451                                                 <argument name="class" required="true" />
452                                         </option>
453                                 </optionlist>
454                         </parameter>
455                 </syntax>
456                 <description>
457                         <para>This application should be executed by an SLA trunk on an inbound call. The channel calling
458                         this application should correspond to the SLA trunk with the name <replaceable>trunk</replaceable>
459                         that is being passed as an argument.</para>
460                         <para>On exit, this application will set the variable <variable>SLATRUNK_STATUS</variable> to
461                         one of the following values:</para>
462                         <variablelist>
463                                 <variable name="SLATRUNK_STATUS">
464                                         <value name="FAILURE" />
465                                         <value name="SUCCESS" />
466                                         <value name="UNANSWERED" />
467                                         <value name="RINGTIMEOUT" />
468                                 </variable>
469                         </variablelist>
470                 </description>
471         </application>
472         <function name="MEETME_INFO" language="en_US">
473                 <synopsis>
474                         Query a given conference of various properties.
475                 </synopsis>
476                 <syntax>
477                         <parameter name="keyword" required="true">
478                                 <para>Options:</para>
479                                 <enumlist>
480                                         <enum name="lock">
481                                                 <para>Boolean of whether the corresponding conference is locked.</para>
482                                         </enum>
483                                         <enum name="parties">
484                                                 <para>Number of parties in a given conference</para>
485                                         </enum>
486                                         <enum name="activity">
487                                                 <para>Duration of conference in seconds.</para>
488                                         </enum>
489                                         <enum name="dynamic">
490                                                 <para>Boolean of whether the corresponding conference is dynamic.</para>
491                                         </enum>
492                                 </enumlist>
493                         </parameter>
494                         <parameter name="confno" required="true">
495                                 <para>Conference number to retrieve information from.</para>
496                         </parameter>
497                 </syntax>
498                 <description />
499                 <see-also>
500                         <ref type="application">MeetMe</ref>
501                         <ref type="application">MeetMeCount</ref>
502                         <ref type="application">MeetMeAdmin</ref>
503                         <ref type="application">MeetMeChannelAdmin</ref>
504                 </see-also>
505         </function>
506         <manager name="MeetmeMute" language="en_US">
507                 <synopsis>
508                         Mute a Meetme user.
509                 </synopsis>
510                 <syntax>
511                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
512                         <parameter name="Meetme" required="true" />
513                         <parameter name="Usernum" required="true" />
514                 </syntax>
515                 <description>
516                 </description>
517         </manager>
518         <manager name="MeetmeUnmute" language="en_US">
519                 <synopsis>
520                         Unmute a Meetme user.
521                 </synopsis>
522                 <syntax>
523                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
524                         <parameter name="Meetme" required="true" />
525                         <parameter name="Usernum" required="true" />
526                 </syntax>
527                 <description>
528                 </description>
529         </manager>
530         <manager name="MeetmeList" language="en_US">
531                 <synopsis>
532                         List participants in a conference.
533                 </synopsis>
534                 <syntax>
535                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
536                         <parameter name="Conference" required="false">
537                                 <para>Conference number.</para>
538                         </parameter>
539                 </syntax>
540                 <description>
541                         <para>Lists all users in a particular MeetMe conference.
542                         MeetmeList will follow as separate events, followed by a final event called
543                         MeetmeListComplete.</para>
544                 </description>
545         </manager>
546         <manager name="MeetmeListRooms" language="en_US">
547                 <synopsis>
548                         List active conferences.
549                 </synopsis>
550                 <syntax>
551                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
552                 </syntax>
553                 <description>
554                         <para>Lists data about all active conferences.
555                                 MeetmeListRooms will follow as separate events, followed by a final event called
556                                 MeetmeListRoomsComplete.</para>
557                 </description>
558         </manager>
559         <managerEvent language="en_US" name="MeetmeJoin">
560                 <managerEventInstance class="EVENT_FLAG_CALL">
561                         <synopsis>Raised when a user joins a MeetMe conference.</synopsis>
562                         <syntax>
563                                 <parameter name="Meetme">
564                                         <para>The identifier for the MeetMe conference.</para>
565                                 </parameter>
566                                 <parameter name="Usernum">
567                                         <para>The identifier of the MeetMe user who joined.</para>
568                                 </parameter>
569                                 <channel_snapshot/>
570                         </syntax>
571                         <see-also>
572                                 <ref type="managerEvent">MeetmeLeave</ref>
573                                 <ref type="application">MeetMe</ref>
574                         </see-also>
575                 </managerEventInstance>
576         </managerEvent>
577         <managerEvent language="en_US" name="MeetmeLeave">
578                 <managerEventInstance class="EVENT_FLAG_CALL">
579                         <synopsis>Raised when a user leaves a MeetMe conference.</synopsis>
580                         <syntax>
581                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='MeetmeJoin']/managerEventInstance/syntax/parameter)" />
582                                 <channel_snapshot/>
583                                 <parameter name="Duration">
584                                         <para>The length of time in seconds that the Meetme user was in the conference.</para>
585                                 </parameter>
586                         </syntax>
587                         <see-also>
588                                 <ref type="managerEvent">MeetmeJoin</ref>
589                         </see-also>
590                 </managerEventInstance>
591         </managerEvent>
592         <managerEvent language="en_US" name="MeetmeEnd">
593                 <managerEventInstance class="EVENT_FLAG_CALL">
594                         <synopsis>Raised when a MeetMe conference ends.</synopsis>
595                         <syntax>
596                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='MeetmeJoin']/managerEventInstance/syntax/parameter[@name='Meetme'])" />
597                         </syntax>
598                         <see-also>
599                                 <ref type="managerEvent">MeetmeJoin</ref>
600                         </see-also>
601                 </managerEventInstance>
602         </managerEvent>
603         <managerEvent language="en_US" name="MeetmeTalkRequest">
604                 <managerEventInstance class="EVENT_FLAG_CALL">
605                         <synopsis>Raised when a MeetMe user has started talking.</synopsis>
606                         <syntax>
607                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='MeetmeJoin']/managerEventInstance/syntax/parameter)" />
608                                 <channel_snapshot/>
609                                 <parameter name="Duration">
610                                         <para>The length of time in seconds that the Meetme user has been in the conference at the time of this event.</para>
611                                 </parameter>
612                                 <parameter name="Status">
613                                         <enumlist>
614                                                 <enum name="on"/>
615                                                 <enum name="off"/>
616                                         </enumlist>
617                                 </parameter>
618                         </syntax>
619                 </managerEventInstance>
620         </managerEvent>
621         <managerEvent language="en_US" name="MeetmeTalking">
622                 <managerEventInstance class="EVENT_FLAG_CALL">
623                         <synopsis>Raised when a MeetMe user begins or ends talking.</synopsis>
624                         <syntax>
625                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='MeetmeJoin']/managerEventInstance/syntax/parameter)" />
626                                 <channel_snapshot/>
627                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='MeetmeTalkRequest']/managerEventInstance/syntax/parameter)" />
628                         </syntax>
629                 </managerEventInstance>
630         </managerEvent>
631         <managerEvent language="en_US" name="MeetmeMute">
632                 <managerEventInstance class="EVENT_FLAG_CALL">
633                         <synopsis>Raised when a MeetMe user is muted or unmuted.</synopsis>
634                         <syntax>
635                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='MeetmeJoin']/managerEventInstance/syntax/parameter)" />
636                                 <channel_snapshot/>
637                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='MeetmeTalkRequest']/managerEventInstance/syntax/parameter)" />
638                         </syntax>
639                 </managerEventInstance>
640         </managerEvent>
641  ***/
642
643 #define CONFIG_FILE_NAME        "meetme.conf"
644 #define SLA_CONFIG_FILE         "sla.conf"
645 #define STR_CONCISE                     "concise"
646
647 /*! each buffer is 20ms, so this is 640ms total */
648 #define DEFAULT_AUDIO_BUFFERS  32
649
650 /*! String format for scheduled conferences */
651 #define DATE_FORMAT "%Y-%m-%d %H:%M:%S"
652
653 enum {
654         ADMINFLAG_MUTED =     (1 << 1), /*!< User is muted */
655         ADMINFLAG_SELFMUTED = (1 << 2), /*!< User muted self */
656         ADMINFLAG_KICKME =    (1 << 3),  /*!< User has been kicked */
657         /*! User has requested to speak */
658         ADMINFLAG_T_REQUEST = (1 << 4),
659         ADMINFLAG_HANGUP = (1 << 5),    /*!< User will be leaving the conference */
660 };
661
662 #define MEETME_DELAYDETECTTALK     300
663 #define MEETME_DELAYDETECTENDTALK  1000
664
665 #define AST_FRAME_BITS  32
666
667 enum volume_action {
668         VOL_UP,
669         VOL_DOWN
670 };
671
672 enum entrance_sound {
673         ENTER,
674         LEAVE
675 };
676
677 enum recording_state {
678         MEETME_RECORD_OFF,
679         MEETME_RECORD_STARTED,
680         MEETME_RECORD_ACTIVE,
681         MEETME_RECORD_TERMINATE
682 };
683
684 #define CONF_SIZE  320
685
686 enum {
687         /*! user has admin access on the conference */
688         CONFFLAG_ADMIN = (1 << 0),
689         /*! If set the user can only receive audio from the conference */
690         CONFFLAG_MONITOR = (1 << 1),
691         /*! If set asterisk will exit conference when key defined in p() option is pressed */
692         CONFFLAG_KEYEXIT = (1 << 2),
693         /*! If set asterisk will provide a menu to the user when '*' is pressed */
694         CONFFLAG_STARMENU = (1 << 3),
695         /*! If set the use can only send audio to the conference */
696         CONFFLAG_TALKER = (1 << 4),
697         /*! If set there will be no enter or leave sounds */
698         CONFFLAG_QUIET = (1 << 5),
699         /*! If set, when user joins the conference, they will be told the number 
700          *  of users that are already in */
701         CONFFLAG_ANNOUNCEUSERCOUNT = (1 << 6),
702         /*! Set to run AGI Script in Background */
703         CONFFLAG_AGI = (1 << 7),
704         /*! Set to have music on hold when user is alone in conference */
705         CONFFLAG_MOH = (1 << 8),
706         /*! If set, the channel will leave the conference if all marked users leave */
707         CONFFLAG_MARKEDEXIT = (1 << 9),
708         /*! If set, the MeetMe will wait until a marked user enters */
709         CONFFLAG_WAITMARKED = (1 << 10),
710         /*! If set, the MeetMe will exit to the specified context */
711         CONFFLAG_EXIT_CONTEXT = (1 << 11),
712         /*! If set, the user will be marked */
713         CONFFLAG_MARKEDUSER = (1 << 12),
714         /*! If set, user will be ask record name on entry of conference */
715         CONFFLAG_INTROUSER = (1 << 13),
716         /*! If set, the MeetMe will be recorded */
717         CONFFLAG_RECORDCONF = (1<< 14),
718         /*! If set, the user will be monitored if the user is talking or not */
719         CONFFLAG_MONITORTALKER = (1 << 15),
720         CONFFLAG_DYNAMIC = (1 << 16),
721         CONFFLAG_DYNAMICPIN = (1 << 17),
722         CONFFLAG_EMPTY = (1 << 18),
723         CONFFLAG_EMPTYNOPIN = (1 << 19),
724         CONFFLAG_ALWAYSPROMPT = (1 << 20),
725         /*! If set, treat talking users as muted users */
726         CONFFLAG_OPTIMIZETALKER = (1 << 21),
727         /*! If set, won't speak the extra prompt when the first person 
728          *  enters the conference */
729         CONFFLAG_NOONLYPERSON = (1 << 22),
730         /*! If set, user will be asked to record name on entry of conference 
731          *  without review */
732         CONFFLAG_INTROUSERNOREVIEW = (1 << 23),
733         /*! If set, the user will be initially self-muted */
734         CONFFLAG_STARTMUTED = (1 << 24),
735         /*! Pass DTMF through the conference */
736         CONFFLAG_PASS_DTMF = (1 << 25),
737         CONFFLAG_SLA_STATION = (1 << 26),
738         CONFFLAG_SLA_TRUNK = (1 << 27),
739         /*! If set, the user should continue in the dialplan if kicked out */
740         CONFFLAG_KICK_CONTINUE = (1 << 28),
741         CONFFLAG_DURATION_STOP = (1 << 29),
742         CONFFLAG_DURATION_LIMIT = (1 << 30),
743 };
744
745 /* These flags are defined separately because we ran out of bits that an enum can be used to represent. 
746    If you add new flags, be sure to do it in the same way that these are. */
747 /*! Do not write any audio to this channel until the state is up. */
748 #define CONFFLAG_NO_AUDIO_UNTIL_UP  (1ULL << 31)
749 #define CONFFLAG_INTROMSG           (1ULL << 32) /*!< If set play an intro announcement at start of conference */
750 #define CONFFLAG_INTROUSER_VMREC    (1ULL << 33)
751 /*! If there's only one person left in a conference when someone leaves, kill the conference */
752 #define CONFFLAG_KILL_LAST_MAN_STANDING (1ULL << 34)
753 /*! If set, don't enable a denoiser for the channel */
754 #define CONFFLAG_DONT_DENOISE       (1ULL << 35)
755
756 enum {
757         OPT_ARG_WAITMARKED = 0,
758         OPT_ARG_EXITKEYS   = 1,
759         OPT_ARG_DURATION_STOP = 2,
760         OPT_ARG_DURATION_LIMIT = 3,
761         OPT_ARG_MOH_CLASS = 4,
762         OPT_ARG_INTROMSG = 5,
763         OPT_ARG_INTROUSER_VMREC = 6,
764         OPT_ARG_ARRAY_SIZE = 7,
765 };
766
767 AST_APP_OPTIONS(meetme_opts, BEGIN_OPTIONS
768         AST_APP_OPTION('A', CONFFLAG_MARKEDUSER ),
769         AST_APP_OPTION('a', CONFFLAG_ADMIN ),
770         AST_APP_OPTION('b', CONFFLAG_AGI ),
771         AST_APP_OPTION('c', CONFFLAG_ANNOUNCEUSERCOUNT ),
772         AST_APP_OPTION('C', CONFFLAG_KICK_CONTINUE),
773         AST_APP_OPTION('D', CONFFLAG_DYNAMICPIN ),
774         AST_APP_OPTION('d', CONFFLAG_DYNAMIC ),
775         AST_APP_OPTION('E', CONFFLAG_EMPTYNOPIN ),
776         AST_APP_OPTION('e', CONFFLAG_EMPTY ),
777         AST_APP_OPTION('F', CONFFLAG_PASS_DTMF ),
778         AST_APP_OPTION_ARG('G', CONFFLAG_INTROMSG, OPT_ARG_INTROMSG ),
779         AST_APP_OPTION_ARG('v', CONFFLAG_INTROUSER_VMREC , OPT_ARG_INTROUSER_VMREC),
780         AST_APP_OPTION('i', CONFFLAG_INTROUSER ),
781         AST_APP_OPTION('I', CONFFLAG_INTROUSERNOREVIEW ),
782         AST_APP_OPTION('k', CONFFLAG_KILL_LAST_MAN_STANDING ),
783         AST_APP_OPTION_ARG('M', CONFFLAG_MOH, OPT_ARG_MOH_CLASS ),
784         AST_APP_OPTION('m', CONFFLAG_STARTMUTED ),
785         AST_APP_OPTION('n', CONFFLAG_DONT_DENOISE ),
786         AST_APP_OPTION('o', CONFFLAG_OPTIMIZETALKER ),
787         AST_APP_OPTION('P', CONFFLAG_ALWAYSPROMPT ),
788         AST_APP_OPTION_ARG('p', CONFFLAG_KEYEXIT, OPT_ARG_EXITKEYS ),
789         AST_APP_OPTION('q', CONFFLAG_QUIET ),
790         AST_APP_OPTION('r', CONFFLAG_RECORDCONF ),
791         AST_APP_OPTION('s', CONFFLAG_STARMENU ),
792         AST_APP_OPTION('T', CONFFLAG_MONITORTALKER ),
793         AST_APP_OPTION('l', CONFFLAG_MONITOR ),
794         AST_APP_OPTION('t', CONFFLAG_TALKER ),
795         AST_APP_OPTION_ARG('w', CONFFLAG_WAITMARKED, OPT_ARG_WAITMARKED ),
796         AST_APP_OPTION('X', CONFFLAG_EXIT_CONTEXT ),
797         AST_APP_OPTION('x', CONFFLAG_MARKEDEXIT ),
798         AST_APP_OPTION('1', CONFFLAG_NOONLYPERSON ),
799         AST_APP_OPTION_ARG('S', CONFFLAG_DURATION_STOP, OPT_ARG_DURATION_STOP),
800         AST_APP_OPTION_ARG('L', CONFFLAG_DURATION_LIMIT, OPT_ARG_DURATION_LIMIT),
801 END_OPTIONS );
802
803 static const char * const app = "MeetMe";
804 static const char * const app2 = "MeetMeCount";
805 static const char * const app3 = "MeetMeAdmin";
806 static const char * const app4 = "MeetMeChannelAdmin";
807 static const char * const slastation_app = "SLAStation";
808 static const char * const slatrunk_app = "SLATrunk";
809
810 /* Lookup RealTime conferences based on confno and current time */
811 static int rt_schedule;
812 static int fuzzystart;
813 static int earlyalert;
814 static int endalert;
815 static int extendby;
816
817 /*! Log participant count to the RealTime backend */
818 static int rt_log_members;
819
820 #define MAX_CONFNUM 80
821 #define MAX_PIN     80
822 #define OPTIONS_LEN 100
823
824 /* Enough space for "<conference #>,<pin>,<admin pin>" followed by a 0 byte. */
825 #define MAX_SETTINGS (MAX_CONFNUM + MAX_PIN + MAX_PIN + 3)
826
827 enum announcetypes {
828         CONF_HASJOIN,
829         CONF_HASLEFT
830 };
831
832 struct announce_listitem {
833         AST_LIST_ENTRY(announce_listitem) entry;
834         char namerecloc[PATH_MAX];                              /*!< Name Recorded file Location */
835         char language[MAX_LANGUAGE];
836         struct ast_channel *confchan;
837         int confusers;
838         int vmrec;
839         enum announcetypes announcetype;
840 };
841
842 /*! \brief The MeetMe Conference object */
843 struct ast_conference {
844         ast_mutex_t playlock;                   /*!< Conference specific lock (players) */
845         ast_mutex_t listenlock;                 /*!< Conference specific lock (listeners) */
846         char confno[MAX_CONFNUM];               /*!< Conference */
847         struct ast_channel *chan;               /*!< Announcements channel */
848         struct ast_channel *lchan;              /*!< Listen/Record channel */
849         int fd;                                 /*!< Announcements fd */
850         int dahdiconf;                            /*!< DAHDI Conf # */
851         int users;                              /*!< Number of active users */
852         int markedusers;                        /*!< Number of marked users */
853         int maxusers;                           /*!< Participant limit if scheduled */
854         int endalert;                           /*!< When to play conf ending message */
855         time_t start;                           /*!< Start time (s) */
856         int refcount;                           /*!< reference count of usage */
857         enum recording_state recording:2;       /*!< recording status */
858         unsigned int isdynamic:1;               /*!< Created on the fly? */
859         unsigned int locked:1;                  /*!< Is the conference locked? */
860         unsigned int gmuted:1;                  /*!< Is the conference globally muted? (all non-admins) */
861         pthread_t recordthread;                 /*!< thread for recording */
862         ast_mutex_t recordthreadlock;           /*!< control threads trying to start recordthread */
863         pthread_attr_t attr;                    /*!< thread attribute */
864         char *recordingfilename;                /*!< Filename to record the Conference into */
865         char *recordingformat;                  /*!< Format to record the Conference in */
866         char pin[MAX_PIN];                      /*!< If protected by a PIN */
867         char pinadmin[MAX_PIN];                 /*!< If protected by a admin PIN */
868         char uniqueid[32];
869         long endtime;                           /*!< When to end the conf if scheduled */
870         const char *useropts;                   /*!< RealTime user flags */
871         const char *adminopts;                  /*!< RealTime moderator flags */
872         const char *bookid;                     /*!< RealTime conference id */
873         struct ast_frame *transframe[32];
874         struct ast_frame *origframe;
875         struct ast_trans_pvt *transpath[32];
876         struct ao2_container *usercontainer;
877         AST_LIST_ENTRY(ast_conference) list;
878         /* announce_thread related data */
879         pthread_t announcethread;
880         ast_mutex_t announcethreadlock;
881         unsigned int announcethread_stop:1;
882         ast_cond_t announcelist_addition;
883         AST_LIST_HEAD_NOLOCK(, announce_listitem) announcelist;
884         ast_mutex_t announcelistlock;
885 };
886
887 static AST_LIST_HEAD_STATIC(confs, ast_conference);
888
889 static unsigned int conf_map[1024] = {0, };
890
891 struct volume {
892         int desired;                            /*!< Desired volume adjustment */
893         int actual;                             /*!< Actual volume adjustment (for channels that can't adjust) */
894 };
895
896 /*! \brief The MeetMe User object */
897 struct ast_conf_user {
898         int user_no;                            /*!< User Number */
899         struct ast_flags64 userflags;           /*!< Flags as set in the conference */
900         int adminflags;                         /*!< Flags set by the Admin */
901         struct ast_channel *chan;               /*!< Connected channel */
902         int talking;                            /*!< Is user talking */
903         int dahdichannel;                       /*!< Is a DAHDI channel */
904         char usrvalue[50];                      /*!< Custom User Value */
905         char namerecloc[PATH_MAX];              /*!< Name Recorded file Location */
906         time_t jointime;                        /*!< Time the user joined the conference */
907         time_t kicktime;                        /*!< Time the user will be kicked from the conference */
908         struct timeval start_time;              /*!< Time the user entered into the conference */
909         long timelimit;                         /*!< Time limit for the user to be in the conference L(x:y:z) */
910         long play_warning;                      /*!< Play a warning when 'y' ms are left */
911         long warning_freq;                      /*!< Repeat the warning every 'z' ms */
912         const char *warning_sound;              /*!< File to play as warning if 'y' is defined */
913         const char *end_sound;                  /*!< File to play when time is up. */
914         struct volume talk;
915         struct volume listen;
916         AST_LIST_ENTRY(ast_conf_user) list;
917 };
918
919 enum sla_which_trunk_refs {
920         ALL_TRUNK_REFS,
921         INACTIVE_TRUNK_REFS,
922 };
923
924 enum sla_trunk_state {
925         SLA_TRUNK_STATE_IDLE,
926         SLA_TRUNK_STATE_RINGING,
927         SLA_TRUNK_STATE_UP,
928         SLA_TRUNK_STATE_ONHOLD,
929         SLA_TRUNK_STATE_ONHOLD_BYME,
930 };
931
932 enum sla_hold_access {
933         /*! This means that any station can put it on hold, and any station
934          * can retrieve the call from hold. */
935         SLA_HOLD_OPEN,
936         /*! This means that only the station that put the call on hold may
937          * retrieve it from hold. */
938         SLA_HOLD_PRIVATE,
939 };
940
941 struct sla_trunk_ref;
942
943 struct sla_station {
944         AST_RWLIST_ENTRY(sla_station) entry;
945         AST_DECLARE_STRING_FIELDS(
946                 AST_STRING_FIELD(name); 
947                 AST_STRING_FIELD(device);       
948                 AST_STRING_FIELD(autocontext);  
949         );
950         AST_LIST_HEAD_NOLOCK(, sla_trunk_ref) trunks;
951         struct ast_dial *dial;
952         /*! Ring timeout for this station, for any trunk.  If a ring timeout
953          *  is set for a specific trunk on this station, that will take
954          *  priority over this value. */
955         unsigned int ring_timeout;
956         /*! Ring delay for this station, for any trunk.  If a ring delay
957          *  is set for a specific trunk on this station, that will take
958          *  priority over this value. */
959         unsigned int ring_delay;
960         /*! This option uses the values in the sla_hold_access enum and sets the
961          * access control type for hold on this station. */
962         unsigned int hold_access:1;
963         /*! Mark used during reload processing */
964         unsigned int mark:1;
965 };
966
967 /*!
968  * \brief A reference to a station
969  *
970  * This struct looks near useless at first glance.  However, its existence
971  * in the list of stations in sla_trunk means that this station references
972  * that trunk.  We use the mark to keep track of whether it needs to be
973  * removed from the sla_trunk's list of stations during a reload.
974  */
975 struct sla_station_ref {
976         AST_LIST_ENTRY(sla_station_ref) entry;
977         struct sla_station *station;
978         /*! Mark used during reload processing */
979         unsigned int mark:1;
980 };
981
982 struct sla_trunk {
983         AST_DECLARE_STRING_FIELDS(
984                 AST_STRING_FIELD(name);
985                 AST_STRING_FIELD(device);
986                 AST_STRING_FIELD(autocontext);  
987         );
988         AST_LIST_HEAD_NOLOCK(, sla_station_ref) stations;
989         /*! Number of stations that use this trunk */
990         unsigned int num_stations;
991         /*! Number of stations currently on a call with this trunk */
992         unsigned int active_stations;
993         /*! Number of stations that have this trunk on hold. */
994         unsigned int hold_stations;
995         struct ast_channel *chan;
996         unsigned int ring_timeout;
997         /*! If set to 1, no station will be able to join an active call with
998          *  this trunk. */
999         unsigned int barge_disabled:1;
1000         /*! This option uses the values in the sla_hold_access enum and sets the
1001          * access control type for hold on this trunk. */
1002         unsigned int hold_access:1;
1003         /*! Whether this trunk is currently on hold, meaning that once a station
1004          *  connects to it, the trunk channel needs to have UNHOLD indicated to it. */
1005         unsigned int on_hold:1;
1006         /*! Mark used during reload processing */
1007         unsigned int mark:1;
1008 };
1009
1010 /*!
1011  * \brief A station's reference to a trunk
1012  *
1013  * An sla_station keeps a list of trunk_refs.  This holds metadata about the
1014  * stations usage of the trunk.
1015  */
1016 struct sla_trunk_ref {
1017         AST_LIST_ENTRY(sla_trunk_ref) entry;
1018         struct sla_trunk *trunk;
1019         enum sla_trunk_state state;
1020         struct ast_channel *chan;
1021         /*! Ring timeout to use when this trunk is ringing on this specific
1022          *  station.  This takes higher priority than a ring timeout set at
1023          *  the station level. */
1024         unsigned int ring_timeout;
1025         /*! Ring delay to use when this trunk is ringing on this specific
1026          *  station.  This takes higher priority than a ring delay set at
1027          *  the station level. */
1028         unsigned int ring_delay;
1029         /*! Mark used during reload processing */
1030         unsigned int mark:1;
1031 };
1032
1033 static struct ao2_container *sla_stations;
1034 static struct ao2_container *sla_trunks;
1035
1036 static const char sla_registrar[] = "SLA";
1037
1038 /*! \brief Event types that can be queued up for the SLA thread */
1039 enum sla_event_type {
1040         /*! A station has put the call on hold */
1041         SLA_EVENT_HOLD,
1042         /*! The state of a dial has changed */
1043         SLA_EVENT_DIAL_STATE,
1044         /*! The state of a ringing trunk has changed */
1045         SLA_EVENT_RINGING_TRUNK,
1046 };
1047
1048 struct sla_event {
1049         enum sla_event_type type;
1050         struct sla_station *station;
1051         struct sla_trunk_ref *trunk_ref;
1052         AST_LIST_ENTRY(sla_event) entry;
1053 };
1054
1055 /*! \brief A station that failed to be dialed 
1056  * \note Only used by the SLA thread. */
1057 struct sla_failed_station {
1058         struct sla_station *station;
1059         struct timeval last_try;
1060         AST_LIST_ENTRY(sla_failed_station) entry;
1061 };
1062
1063 /*! \brief A trunk that is ringing */
1064 struct sla_ringing_trunk {
1065         struct sla_trunk *trunk;
1066         /*! The time that this trunk started ringing */
1067         struct timeval ring_begin;
1068         AST_LIST_HEAD_NOLOCK(, sla_station_ref) timed_out_stations;
1069         AST_LIST_ENTRY(sla_ringing_trunk) entry;
1070 };
1071
1072 enum sla_station_hangup {
1073         SLA_STATION_HANGUP_NORMAL,
1074         SLA_STATION_HANGUP_TIMEOUT,
1075 };
1076
1077 /*! \brief A station that is ringing */
1078 struct sla_ringing_station {
1079         struct sla_station *station;
1080         /*! The time that this station started ringing */
1081         struct timeval ring_begin;
1082         AST_LIST_ENTRY(sla_ringing_station) entry;
1083 };
1084
1085 /*!
1086  * \brief A structure for data used by the sla thread
1087  */
1088 static struct {
1089         /*! The SLA thread ID */
1090         pthread_t thread;
1091         ast_cond_t cond;
1092         ast_mutex_t lock;
1093         AST_LIST_HEAD_NOLOCK(, sla_ringing_trunk) ringing_trunks;
1094         AST_LIST_HEAD_NOLOCK(, sla_ringing_station) ringing_stations;
1095         AST_LIST_HEAD_NOLOCK(, sla_failed_station) failed_stations;
1096         AST_LIST_HEAD_NOLOCK(, sla_event) event_q;
1097         unsigned int stop:1;
1098         /*! Attempt to handle CallerID, even though it is known not to work
1099          *  properly in some situations. */
1100         unsigned int attempt_callerid:1;
1101 } sla = {
1102         .thread = AST_PTHREADT_NULL,
1103 };
1104
1105 /*! \brief The number of audio buffers to be allocated on pseudo channels
1106  *  when in a conference */
1107 static int audio_buffers;
1108
1109 /*! \brief Map 'volume' levels from -5 through +5 into decibel (dB) 
1110  *    settings for channel drivers.
1111  *
1112  *  \note these are not a straight linear-to-dB
1113  *  conversion... the numbers have been modified
1114  *  to give the user a better level of adjustability.
1115  */
1116 static const char gain_map[] = {
1117         -15,
1118         -13,
1119         -10,
1120         -6,
1121         0,
1122         0,
1123         0,
1124         6,
1125         10,
1126         13,
1127         15,
1128 };
1129
1130 /* Routes the various meetme message types to the meetme stasis callback function to turn them into events */
1131 static struct stasis_message_router *meetme_event_message_router;
1132
1133 STASIS_MESSAGE_TYPE_DEFN_LOCAL(meetme_join_type);
1134 STASIS_MESSAGE_TYPE_DEFN_LOCAL(meetme_leave_type);
1135 STASIS_MESSAGE_TYPE_DEFN_LOCAL(meetme_end_type);
1136 STASIS_MESSAGE_TYPE_DEFN_LOCAL(meetme_mute_type);
1137 STASIS_MESSAGE_TYPE_DEFN_LOCAL(meetme_talking_type);
1138 STASIS_MESSAGE_TYPE_DEFN_LOCAL(meetme_talk_request_type);
1139
1140 static void meetme_stasis_cb(void *data, struct stasis_subscription *sub,
1141         struct stasis_message *message);
1142
1143 static void meetme_stasis_cleanup(void)
1144 {
1145         if (meetme_event_message_router) {
1146                 stasis_message_router_unsubscribe(meetme_event_message_router);
1147                 meetme_event_message_router = NULL;
1148         }
1149
1150         STASIS_MESSAGE_TYPE_CLEANUP(meetme_join_type);
1151         STASIS_MESSAGE_TYPE_CLEANUP(meetme_leave_type);
1152         STASIS_MESSAGE_TYPE_CLEANUP(meetme_end_type);
1153         STASIS_MESSAGE_TYPE_CLEANUP(meetme_mute_type);
1154         STASIS_MESSAGE_TYPE_CLEANUP(meetme_talking_type);
1155         STASIS_MESSAGE_TYPE_CLEANUP(meetme_talk_request_type);
1156 }
1157
1158 static int meetme_stasis_init(void)
1159 {
1160
1161         STASIS_MESSAGE_TYPE_INIT(meetme_join_type);
1162         STASIS_MESSAGE_TYPE_INIT(meetme_leave_type);
1163         STASIS_MESSAGE_TYPE_INIT(meetme_end_type);
1164         STASIS_MESSAGE_TYPE_INIT(meetme_mute_type);
1165         STASIS_MESSAGE_TYPE_INIT(meetme_talking_type);
1166         STASIS_MESSAGE_TYPE_INIT(meetme_talk_request_type);
1167
1168         meetme_event_message_router = stasis_message_router_create(
1169                 ast_channel_topic_all_cached());
1170
1171         if (!meetme_event_message_router) {
1172                 meetme_stasis_cleanup();
1173                 return -1;
1174         }
1175
1176         if (stasis_message_router_add(meetme_event_message_router,
1177                         meetme_join_type(),
1178                         meetme_stasis_cb,
1179                         NULL)) {
1180                 meetme_stasis_cleanup();
1181                 return -1;
1182         }
1183
1184         if (stasis_message_router_add(meetme_event_message_router,
1185                         meetme_leave_type(),
1186                         meetme_stasis_cb,
1187                         NULL)) {
1188                 meetme_stasis_cleanup();
1189                 return -1;
1190         }
1191
1192         if (stasis_message_router_add(meetme_event_message_router,
1193                         meetme_end_type(),
1194                         meetme_stasis_cb,
1195                         NULL)) {
1196                 meetme_stasis_cleanup();
1197                 return -1;
1198         }
1199
1200         if (stasis_message_router_add(meetme_event_message_router,
1201                         meetme_mute_type(),
1202                         meetme_stasis_cb,
1203                         NULL)) {
1204                 meetme_stasis_cleanup();
1205                 return -1;
1206         }
1207
1208         if (stasis_message_router_add(meetme_event_message_router,
1209                         meetme_talking_type(),
1210                         meetme_stasis_cb,
1211                         NULL)) {
1212                 meetme_stasis_cleanup();
1213                 return -1;
1214         }
1215
1216         if (stasis_message_router_add(meetme_event_message_router,
1217                         meetme_talk_request_type(),
1218                         meetme_stasis_cb,
1219                         NULL)) {
1220                 meetme_stasis_cleanup();
1221                 return -1;
1222         }
1223
1224         return 0;
1225 }
1226
1227 static void meetme_stasis_cb(void *data, struct stasis_subscription *sub,
1228         struct stasis_message *message)
1229 {
1230         struct ast_channel_blob *channel_blob = stasis_message_data(message);
1231         struct stasis_message_type *message_type;
1232         const char *event;
1233         const char *conference_num;
1234         const char *status;
1235         struct ast_json *json_cur;
1236         RAII_VAR(struct ast_str *, channel_text, NULL, ast_free);
1237         RAII_VAR(struct ast_str *, extra_text, NULL, ast_free);
1238
1239         if (!channel_blob) {
1240                 ast_assert(0);
1241                 return;
1242         }
1243
1244         message_type = stasis_message_type(message);
1245
1246         if (!message_type) {
1247                 ast_assert(0);
1248                 return;
1249         }
1250
1251         if (message_type == meetme_join_type()) {
1252                 event = "MeetmeJoin";
1253         } else if (message_type == meetme_leave_type()) {
1254                 event = "MeetmeLeave";
1255         } else if (message_type == meetme_end_type()) {
1256                 event = "MeetmeEnd";
1257         } else if (message_type == meetme_mute_type()) {
1258                 event = "MeetmeMute";
1259         } else if (message_type == meetme_talking_type()) {
1260                 event = "MeetmeTalking";
1261         } else if (message_type == meetme_talk_request_type()) {
1262                 event = "MeetmeTalkRequest";
1263         } else {
1264                 ast_assert(0);
1265                 return;
1266         }
1267
1268         if (!event) {
1269                 ast_assert(0);
1270                 return;
1271         }
1272
1273         conference_num = ast_json_string_get(ast_json_object_get(channel_blob->blob, "Meetme"));
1274         if (!conference_num) {
1275                 ast_assert(0);
1276                 return;
1277         }
1278
1279         status = ast_json_string_get(ast_json_object_get(channel_blob->blob, "status"));
1280         if (status) {
1281                 ast_str_append_event_header(&extra_text, "Status", status);
1282         }
1283
1284         if (channel_blob->snapshot) {
1285                 channel_text = ast_manager_build_channel_state_string(channel_blob->snapshot);
1286         }
1287
1288         if ((json_cur = ast_json_object_get(channel_blob->blob, "user"))) {
1289                 int user_number = ast_json_integer_get(json_cur);
1290                 RAII_VAR(struct ast_str *, user_prop_str, ast_str_create(32), ast_free);
1291                 if (!user_prop_str) {
1292                         return;
1293                 }
1294
1295                 ast_str_set(&user_prop_str, 0, "%d", user_number);
1296                 ast_str_append_event_header(&extra_text, "User", ast_str_buffer(user_prop_str));
1297
1298                 if ((json_cur = ast_json_object_get(channel_blob->blob, "duration"))) {
1299                         int duration = ast_json_integer_get(json_cur);
1300                         ast_str_set(&user_prop_str, 0, "%d", duration);
1301                         ast_str_append_event_header(&extra_text, "Duration", ast_str_buffer(user_prop_str));
1302                 }
1303
1304                 json_cur = NULL;
1305         }
1306
1307         manager_event(EVENT_FLAG_CALL, event,
1308                 "Meetme: %s\r\n"
1309                 "%s"
1310                 "%s",
1311                 conference_num,
1312                 channel_text ? ast_str_buffer(channel_text) : "",
1313                 extra_text ? ast_str_buffer(extra_text) : "");
1314 }
1315
1316 /*!
1317  * \internal
1318  * \brief Build a json object from a status value for inclusion in json extras for meetme_stasis_generate_msg
1319  * \since 12.0.0
1320  *
1321  * \param on if true, then status is on. Otherwise status is off
1322  * \retval NULL on failure to allocate the JSON blob.
1323  * \retval pointer to the JSON blob if successful.
1324  */
1325 static struct ast_json *status_to_json(int on)
1326 {
1327         struct ast_json *json_object = ast_json_pack("{s: s}",
1328                 "status", on ? "on" : "off");
1329
1330         return json_object;
1331 }
1332
1333 /*!
1334  * \internal
1335  * \brief Generate a stasis message associated with a meetme event
1336  * \since 12.0.0
1337  *
1338  * \param meetme_confere The conference responsible for generating this message
1339  * \param chan The channel involved in the message (NULL allowed)
1340  * \param user The conference user involved in the message (NULL allowed)
1341  * \param message_type the type the stasis message being generated
1342  * \param extras Additional json fields desired for inclusion
1343  */
1344 static void meetme_stasis_generate_msg(struct ast_conference *meetme_conference, struct ast_channel *chan,
1345         struct ast_conf_user *user, struct stasis_message_type *message_type, struct ast_json *extras)
1346 {
1347         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
1348         RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
1349
1350         json_object = ast_json_pack("{s: s}",
1351                 "Meetme", meetme_conference->confno);
1352
1353         if (!json_object) {
1354                 return;
1355         }
1356
1357         if (extras) {
1358                 ast_json_object_update(json_object, extras);
1359         }
1360
1361         if (user) {
1362                 struct timeval now = ast_tvnow();
1363                 long duration = (long)(now.tv_sec - user->jointime);
1364                 struct ast_json *json_user;
1365                 struct ast_json *json_user_duration;
1366
1367                 json_user = ast_json_integer_create(user->user_no);
1368                 if (!json_user || ast_json_object_set(json_object, "user", json_user)) {
1369                         return;
1370                 }
1371
1372                 if (duration > 0) {
1373                         json_user_duration = ast_json_integer_create(duration);
1374                         if (!json_user_duration
1375                                 || ast_json_object_set(json_object, "duration", json_user_duration)) {
1376                                 return;
1377                         }
1378                 }
1379         }
1380
1381         if (chan) {
1382                 ast_channel_lock(chan);
1383         }
1384         msg = ast_channel_blob_create(chan, message_type, json_object);
1385         if (chan) {
1386                 ast_channel_unlock(chan);
1387         }
1388
1389         if (!msg) {
1390                 return;
1391         }
1392
1393         stasis_publish(ast_channel_topic(chan), msg);
1394 }
1395
1396 static int admin_exec(struct ast_channel *chan, const char *data);
1397 static void *recordthread(void *args);
1398
1399 static const char *istalking(int x)
1400 {
1401         if (x > 0)
1402                 return "(talking)";
1403         else if (x < 0)
1404                 return "(unmonitored)";
1405         else 
1406                 return "(not talking)";
1407 }
1408
1409 static int careful_write(int fd, unsigned char *data, int len, int block)
1410 {
1411         int res;
1412         int x;
1413
1414         while (len) {
1415                 if (block) {
1416                         x = DAHDI_IOMUX_WRITE | DAHDI_IOMUX_SIGEVENT;
1417                         res = ioctl(fd, DAHDI_IOMUX, &x);
1418                 } else
1419                         res = 0;
1420                 if (res >= 0)
1421                         res = write(fd, data, len);
1422                 if (res < 1) {
1423                         if (errno != EAGAIN) {
1424                                 ast_log(LOG_WARNING, "Failed to write audio data to conference: %s\n", strerror(errno));
1425                                 return -1;
1426                         } else
1427                                 return 0;
1428                 }
1429                 len -= res;
1430                 data += res;
1431         }
1432
1433         return 0;
1434 }
1435
1436 static int set_talk_volume(struct ast_conf_user *user, int volume)
1437 {
1438         char gain_adjust;
1439
1440         /* attempt to make the adjustment in the channel driver;
1441            if successful, don't adjust in the frame reading routine
1442         */
1443         gain_adjust = gain_map[volume + 5];
1444
1445         return ast_channel_setoption(user->chan, AST_OPTION_RXGAIN, &gain_adjust, sizeof(gain_adjust), 0);
1446 }
1447
1448 static int set_listen_volume(struct ast_conf_user *user, int volume)
1449 {
1450         char gain_adjust;
1451
1452         /* attempt to make the adjustment in the channel driver;
1453            if successful, don't adjust in the frame reading routine
1454         */
1455         gain_adjust = gain_map[volume + 5];
1456
1457         return ast_channel_setoption(user->chan, AST_OPTION_TXGAIN, &gain_adjust, sizeof(gain_adjust), 0);
1458 }
1459
1460 static void tweak_volume(struct volume *vol, enum volume_action action)
1461 {
1462         switch (action) {
1463         case VOL_UP:
1464                 switch (vol->desired) { 
1465                 case 5:
1466                         break;
1467                 case 0:
1468                         vol->desired = 2;
1469                         break;
1470                 case -2:
1471                         vol->desired = 0;
1472                         break;
1473                 default:
1474                         vol->desired++;
1475                         break;
1476                 }
1477                 break;
1478         case VOL_DOWN:
1479                 switch (vol->desired) {
1480                 case -5:
1481                         break;
1482                 case 2:
1483                         vol->desired = 0;
1484                         break;
1485                 case 0:
1486                         vol->desired = -2;
1487                         break;
1488                 default:
1489                         vol->desired--;
1490                         break;
1491                 }
1492         }
1493 }
1494
1495 static void tweak_talk_volume(struct ast_conf_user *user, enum volume_action action)
1496 {
1497         tweak_volume(&user->talk, action);
1498         /* attempt to make the adjustment in the channel driver;
1499            if successful, don't adjust in the frame reading routine
1500         */
1501         if (!set_talk_volume(user, user->talk.desired))
1502                 user->talk.actual = 0;
1503         else
1504                 user->talk.actual = user->talk.desired;
1505 }
1506
1507 static void tweak_listen_volume(struct ast_conf_user *user, enum volume_action action)
1508 {
1509         tweak_volume(&user->listen, action);
1510         /* attempt to make the adjustment in the channel driver;
1511            if successful, don't adjust in the frame reading routine
1512         */
1513         if (!set_listen_volume(user, user->listen.desired))
1514                 user->listen.actual = 0;
1515         else
1516                 user->listen.actual = user->listen.desired;
1517 }
1518
1519 static void reset_volumes(struct ast_conf_user *user)
1520 {
1521         signed char zero_volume = 0;
1522
1523         ast_channel_setoption(user->chan, AST_OPTION_TXGAIN, &zero_volume, sizeof(zero_volume), 0);
1524         ast_channel_setoption(user->chan, AST_OPTION_RXGAIN, &zero_volume, sizeof(zero_volume), 0);
1525 }
1526
1527 static void conf_play(struct ast_channel *chan, struct ast_conference *conf, enum entrance_sound sound)
1528 {
1529         unsigned char *data;
1530         int len;
1531         int res = -1;
1532
1533         ast_test_suite_event_notify("CONFPLAY", "Channel: %s\r\n"
1534                 "Conference: %s\r\n"
1535                 "Marked: %d",
1536                 ast_channel_name(chan),
1537                 conf->confno,
1538                 conf->markedusers);
1539
1540         if (!ast_check_hangup(chan))
1541                 res = ast_autoservice_start(chan);
1542
1543         AST_LIST_LOCK(&confs);
1544
1545         switch(sound) {
1546         case ENTER:
1547                 data = enter;
1548                 len = sizeof(enter);
1549                 break;
1550         case LEAVE:
1551                 data = leave;
1552                 len = sizeof(leave);
1553                 break;
1554         default:
1555                 data = NULL;
1556                 len = 0;
1557         }
1558         if (data) {
1559                 careful_write(conf->fd, data, len, 1);
1560         }
1561
1562         AST_LIST_UNLOCK(&confs);
1563
1564         if (!res) 
1565                 ast_autoservice_stop(chan);
1566 }
1567
1568 static int user_no_cmp(void *obj, void *arg, int flags)
1569 {
1570         struct ast_conf_user *user = obj;
1571         int *user_no = arg;
1572
1573         if (user->user_no == *user_no) {
1574                 return (CMP_MATCH | CMP_STOP);
1575         }
1576
1577         return 0;
1578 }
1579
1580 static int user_max_cmp(void *obj, void *arg, int flags)
1581 {
1582         struct ast_conf_user *user = obj;
1583         int *max_no = arg;
1584
1585         if (user->user_no > *max_no) {
1586                 *max_no = user->user_no;
1587         }
1588
1589         return 0;
1590 }
1591
1592 /*!
1593  * \brief Find or create a conference
1594  *
1595  * \param confno The conference name/number
1596  * \param pin The regular user pin
1597  * \param pinadmin The admin pin
1598  * \param make Make the conf if it doesn't exist
1599  * \param dynamic Mark the newly created conference as dynamic
1600  * \param refcount How many references to mark on the conference
1601  * \param chan The asterisk channel
1602  * \param test
1603  *
1604  * \return A pointer to the conference struct, or NULL if it wasn't found and
1605  *         make or dynamic were not set.
1606  */
1607 static struct ast_conference *build_conf(const char *confno, const char *pin,
1608         const char *pinadmin, int make, int dynamic, int refcount,
1609         const struct ast_channel *chan, struct ast_test *test)
1610 {
1611         struct ast_conference *cnf;
1612         struct dahdi_confinfo dahdic = { 0, };
1613         int confno_int = 0;
1614         struct ast_format_cap *cap_slin = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
1615
1616         AST_LIST_LOCK(&confs);
1617
1618         AST_LIST_TRAVERSE(&confs, cnf, list) {
1619                 if (!strcmp(confno, cnf->confno)) 
1620                         break;
1621         }
1622
1623         if (cnf || (!make && !dynamic) || !cap_slin)
1624                 goto cnfout;
1625
1626         ast_format_cap_append(cap_slin, ast_format_slin, 0);
1627         /* Make a new one */
1628         if (!(cnf = ast_calloc(1, sizeof(*cnf))) ||
1629                 !(cnf->usercontainer = ao2_container_alloc(1, NULL, user_no_cmp))) {
1630                 goto cnfout;
1631         }
1632
1633         ast_mutex_init(&cnf->playlock);
1634         ast_mutex_init(&cnf->listenlock);
1635         cnf->recordthread = AST_PTHREADT_NULL;
1636         ast_mutex_init(&cnf->recordthreadlock);
1637         cnf->announcethread = AST_PTHREADT_NULL;
1638         ast_mutex_init(&cnf->announcethreadlock);
1639         ast_copy_string(cnf->confno, confno, sizeof(cnf->confno));
1640         ast_copy_string(cnf->pin, pin, sizeof(cnf->pin));
1641         ast_copy_string(cnf->pinadmin, pinadmin, sizeof(cnf->pinadmin));
1642         ast_copy_string(cnf->uniqueid, ast_channel_uniqueid(chan), sizeof(cnf->uniqueid));
1643
1644         /* Setup a new dahdi conference */
1645         dahdic.confno = -1;
1646         dahdic.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON;
1647         cnf->fd = open("/dev/dahdi/pseudo", O_RDWR);
1648         if (cnf->fd < 0 || ioctl(cnf->fd, DAHDI_SETCONF, &dahdic)) {
1649                 if (test) {
1650                         /* if we are creating a conference for a unit test, it is not neccesary
1651                          * to open a pseudo channel, so, if we fail continue creating
1652                          * the conference. */
1653                         ast_test_status_update(test, "Unable to open DAHDI pseudo device\n");
1654                 } else {
1655                         ast_log(LOG_WARNING, "Unable to open DAHDI pseudo device\n");
1656                         if (cnf->fd >= 0)
1657                                 close(cnf->fd);
1658                         ao2_ref(cnf->usercontainer, -1);
1659                         ast_mutex_destroy(&cnf->playlock);
1660                         ast_mutex_destroy(&cnf->listenlock);
1661                         ast_mutex_destroy(&cnf->recordthreadlock);
1662                         ast_mutex_destroy(&cnf->announcethreadlock);
1663                         ast_free(cnf);
1664                         cnf = NULL;
1665                         goto cnfout;
1666                 }
1667         }
1668
1669         cnf->dahdiconf = dahdic.confno;
1670
1671         /* Setup a new channel for playback of audio files */
1672         cnf->chan = ast_request("DAHDI", cap_slin, NULL, chan, "pseudo", NULL);
1673         if (cnf->chan) {
1674                 ast_set_read_format(cnf->chan, ast_format_slin);
1675                 ast_set_write_format(cnf->chan, ast_format_slin);
1676                 dahdic.chan = 0;
1677                 dahdic.confno = cnf->dahdiconf;
1678                 dahdic.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON;
1679                 if (ioctl(ast_channel_fd(cnf->chan, 0), DAHDI_SETCONF, &dahdic)) {
1680                         if (test) {
1681                                 ast_test_status_update(test, "Error setting conference on pseudo channel\n");
1682                         }
1683                         ast_log(LOG_WARNING, "Error setting conference\n");
1684                         if (cnf->chan)
1685                                 ast_hangup(cnf->chan);
1686                         else
1687                                 close(cnf->fd);
1688                         ao2_ref(cnf->usercontainer, -1);
1689                         ast_mutex_destroy(&cnf->playlock);
1690                         ast_mutex_destroy(&cnf->listenlock);
1691                         ast_mutex_destroy(&cnf->recordthreadlock);
1692                         ast_mutex_destroy(&cnf->announcethreadlock);
1693                         ast_free(cnf);
1694                         cnf = NULL;
1695                         goto cnfout;
1696                 }
1697         }
1698
1699         /* Fill the conference struct */
1700         cnf->start = time(NULL);
1701         cnf->maxusers = 0x7fffffff;
1702         cnf->isdynamic = dynamic ? 1 : 0;
1703         ast_verb(3, "Created MeetMe conference %d for conference '%s'\n", cnf->dahdiconf, cnf->confno);
1704         AST_LIST_INSERT_HEAD(&confs, cnf, list);
1705
1706         /* Reserve conference number in map */
1707         if ((sscanf(cnf->confno, "%30d", &confno_int) == 1) && (confno_int >= 0 && confno_int < 1024))
1708                 conf_map[confno_int] = 1;
1709         
1710 cnfout:
1711         ao2_cleanup(cap_slin);
1712         if (cnf)
1713                 ast_atomic_fetchadd_int(&cnf->refcount, refcount);
1714
1715         AST_LIST_UNLOCK(&confs);
1716
1717         return cnf;
1718 }
1719
1720 static char *complete_confno(const char *word, int state)
1721 {
1722         struct ast_conference *cnf;
1723         char *ret = NULL;
1724         int which = 0;
1725         int len = strlen(word);
1726
1727         AST_LIST_LOCK(&confs);
1728         AST_LIST_TRAVERSE(&confs, cnf, list) {
1729                 if (!strncmp(word, cnf->confno, len) && ++which > state) {
1730                         /* dup before releasing the lock */
1731                         ret = ast_strdup(cnf->confno);
1732                         break;
1733                 }
1734         }
1735         AST_LIST_UNLOCK(&confs);
1736         return ret;
1737 }
1738
1739 static char *complete_userno(struct ast_conference *cnf, const char *word, int state)
1740 {
1741         char usrno[50];
1742         struct ao2_iterator iter;
1743         struct ast_conf_user *usr;
1744         char *ret = NULL;
1745         int which = 0;
1746         int len = strlen(word);
1747
1748         iter = ao2_iterator_init(cnf->usercontainer, 0);
1749         for (; (usr = ao2_iterator_next(&iter)); ao2_ref(usr, -1)) {
1750                 snprintf(usrno, sizeof(usrno), "%d", usr->user_no);
1751                 if (!strncmp(word, usrno, len) && ++which > state) {
1752                         ao2_ref(usr, -1);
1753                         ret = ast_strdup(usrno);
1754                         break;
1755                 }
1756         }
1757         ao2_iterator_destroy(&iter);
1758         return ret;
1759 }
1760
1761 static char *complete_meetmecmd_mute_kick(const char *line, const char *word, int pos, int state)
1762 {
1763         if (pos == 2) {
1764                 return complete_confno(word, state);
1765         }
1766         if (pos == 3) {
1767                 int len = strlen(word);
1768                 char *ret = NULL;
1769                 char *saved = NULL;
1770                 char *myline;
1771                 char *confno;
1772                 struct ast_conference *cnf;
1773
1774                 if (!strncasecmp(word, "all", len)) {
1775                         if (state == 0) {
1776                                 return ast_strdup("all");
1777                         }
1778                         --state;
1779                 }
1780
1781                 /* Extract the confno from the command line. */
1782                 myline = ast_strdupa(line);
1783                 strtok_r(myline, " ", &saved);
1784                 strtok_r(NULL, " ", &saved);
1785                 confno = strtok_r(NULL, " ", &saved);
1786
1787                 AST_LIST_LOCK(&confs);
1788                 AST_LIST_TRAVERSE(&confs, cnf, list) {
1789                         if (!strcmp(confno, cnf->confno)) {
1790                                 ret = complete_userno(cnf, word, state);
1791                                 break;
1792                         }
1793                 }
1794                 AST_LIST_UNLOCK(&confs);
1795
1796                 return ret;
1797         }
1798         return NULL;
1799 }
1800
1801 static char *complete_meetmecmd_lock(const char *word, int pos, int state)
1802 {
1803         if (pos == 2) {
1804                 return complete_confno(word, state);
1805         }
1806         return NULL;
1807 }
1808
1809 static char *complete_meetmecmd_list(const char *line, const char *word, int pos, int state)
1810 {
1811         int len;
1812
1813         if (pos == 2) {
1814                 len = strlen(word);
1815                 if (!strncasecmp(word, STR_CONCISE, len)) {
1816                         if (state == 0) {
1817                                 return ast_strdup(STR_CONCISE);
1818                         }
1819                         --state;
1820                 }
1821
1822                 return complete_confno(word, state);
1823         }
1824         if (pos == 3 && state == 0) {
1825                 char *saved = NULL;
1826                 char *myline;
1827                 char *confno;
1828
1829                 /* Extract the confno from the command line. */
1830                 myline = ast_strdupa(line);
1831                 strtok_r(myline, " ", &saved);
1832                 strtok_r(NULL, " ", &saved);
1833                 confno = strtok_r(NULL, " ", &saved);
1834
1835                 if (!strcasecmp(confno, STR_CONCISE)) {
1836                         /* There is nothing valid in this position now. */
1837                         return NULL;
1838                 }
1839
1840                 len = strlen(word);
1841                 if (!strncasecmp(word, STR_CONCISE, len)) {
1842                         return ast_strdup(STR_CONCISE);
1843                 }
1844         }
1845         return NULL;
1846 }
1847
1848 static char *meetme_show_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1849 {
1850         /* Process the command */
1851         struct ast_conf_user *user;
1852         struct ast_conference *cnf;
1853         int hr, min, sec;
1854         int total = 0;
1855         time_t now;
1856 #define MC_HEADER_FORMAT "%-14s %-14s %-10s %-8s  %-8s  %-6s\n"
1857 #define MC_DATA_FORMAT "%-12.12s   %4.4d              %4.4s       %02d:%02d:%02d  %-8s  %-6s\n"
1858
1859         switch (cmd) {
1860         case CLI_INIT:
1861                 e->command = "meetme list";
1862                 e->usage =
1863                         "Usage: meetme list [<confno>] [" STR_CONCISE "]\n"
1864                         "       List all conferences or a specific conference.\n";
1865                 return NULL;
1866         case CLI_GENERATE:
1867                 return complete_meetmecmd_list(a->line, a->word, a->pos, a->n);
1868         }
1869
1870         if (a->argc == 2 || (a->argc == 3 && !strcasecmp(a->argv[2], STR_CONCISE))) {
1871                 /* List all the conferences */
1872                 int concise = (a->argc == 3);
1873                 struct ast_str *marked_users;
1874
1875                 if (!(marked_users = ast_str_create(30))) {
1876                         return CLI_FAILURE;
1877                 }
1878
1879                 now = time(NULL);
1880                 AST_LIST_LOCK(&confs);
1881                 if (AST_LIST_EMPTY(&confs)) {
1882                         if (!concise) {
1883                                 ast_cli(a->fd, "No active MeetMe conferences.\n");
1884                         }
1885                         AST_LIST_UNLOCK(&confs);
1886                         ast_free(marked_users);
1887                         return CLI_SUCCESS;
1888                 }
1889                 if (!concise) {
1890                         ast_cli(a->fd, MC_HEADER_FORMAT, "Conf Num", "Parties", "Marked", "Activity", "Creation", "Locked");
1891                 }
1892                 AST_LIST_TRAVERSE(&confs, cnf, list) {
1893                         hr = (now - cnf->start) / 3600;
1894                         min = ((now - cnf->start) % 3600) / 60;
1895                         sec = (now - cnf->start) % 60;
1896                         if (!concise) {
1897                                 if (cnf->markedusers == 0) {
1898                                         ast_str_set(&marked_users, 0, "N/A ");
1899                                 } else {
1900                                         ast_str_set(&marked_users, 0, "%4.4d", cnf->markedusers);
1901                                 }
1902                                 ast_cli(a->fd, MC_DATA_FORMAT, cnf->confno, cnf->users,
1903                                         ast_str_buffer(marked_users), hr, min, sec,
1904                                         cnf->isdynamic ? "Dynamic" : "Static", cnf->locked ? "Yes" : "No");
1905                         } else {
1906                                 ast_cli(a->fd, "%s!%d!%d!%02d:%02d:%02d!%d!%d\n",
1907                                         cnf->confno,
1908                                         cnf->users,
1909                                         cnf->markedusers,
1910                                         hr, min, sec,
1911                                         cnf->isdynamic,
1912                                         cnf->locked);
1913                         }
1914
1915                         total += cnf->users;
1916                 }
1917                 AST_LIST_UNLOCK(&confs);
1918                 if (!concise) {
1919                         ast_cli(a->fd, "* Total number of MeetMe users: %d\n", total);
1920                 }
1921                 ast_free(marked_users);
1922                 return CLI_SUCCESS;
1923         }
1924         if (a->argc == 3 || (a->argc == 4 && !strcasecmp(a->argv[3], STR_CONCISE))) {
1925                 struct ao2_iterator user_iter;
1926                 int concise = (a->argc == 4);
1927
1928                 /* List all the users in a conference */
1929                 if (AST_LIST_EMPTY(&confs)) {
1930                         if (!concise) {
1931                                 ast_cli(a->fd, "No active MeetMe conferences.\n");
1932                         }
1933                         return CLI_SUCCESS;
1934                 }
1935                 /* Find the right conference */
1936                 AST_LIST_LOCK(&confs);
1937                 AST_LIST_TRAVERSE(&confs, cnf, list) {
1938                         if (strcmp(cnf->confno, a->argv[2]) == 0) {
1939                                 break;
1940                         }
1941                 }
1942                 if (!cnf) {
1943                         if (!concise)
1944                                 ast_cli(a->fd, "No such conference: %s.\n", a->argv[2]);
1945                         AST_LIST_UNLOCK(&confs);
1946                         return CLI_SUCCESS;
1947                 }
1948                 /* Show all the users */
1949                 time(&now);
1950                 user_iter = ao2_iterator_init(cnf->usercontainer, 0);
1951                 while((user = ao2_iterator_next(&user_iter))) {
1952                         hr = (now - user->jointime) / 3600;
1953                         min = ((now - user->jointime) % 3600) / 60;
1954                         sec = (now - user->jointime) % 60;
1955                         if (!concise) {
1956                                 ast_cli(a->fd, "User #: %-2.2d %12.12s %-20.20s Channel: %s %s %s %s %s %s %02d:%02d:%02d\n",
1957                                         user->user_no,
1958                                         S_COR(ast_channel_caller(user->chan)->id.number.valid, ast_channel_caller(user->chan)->id.number.str, "<unknown>"),
1959                                         S_COR(ast_channel_caller(user->chan)->id.name.valid, ast_channel_caller(user->chan)->id.name.str, "<no name>"),
1960                                         ast_channel_name(user->chan),
1961                                         ast_test_flag64(&user->userflags, CONFFLAG_ADMIN) ? "(Admin)" : "",
1962                                         ast_test_flag64(&user->userflags, CONFFLAG_MONITOR) ? "(Listen only)" : "",
1963                                         user->adminflags & ADMINFLAG_MUTED ? "(Admin Muted)" : user->adminflags & ADMINFLAG_SELFMUTED ? "(Muted)" : "",
1964                                         user->adminflags & ADMINFLAG_T_REQUEST ? "(Request to Talk)" : "",
1965                                         istalking(user->talking), hr, min, sec); 
1966                         } else {
1967                                 ast_cli(a->fd, "%d!%s!%s!%s!%s!%s!%s!%s!%d!%02d:%02d:%02d\n",
1968                                         user->user_no,
1969                                         S_COR(ast_channel_caller(user->chan)->id.number.valid, ast_channel_caller(user->chan)->id.number.str, ""),
1970                                         S_COR(ast_channel_caller(user->chan)->id.name.valid, ast_channel_caller(user->chan)->id.name.str, ""),
1971                                         ast_channel_name(user->chan),
1972                                         ast_test_flag64(&user->userflags, CONFFLAG_ADMIN) ? "1" : "",
1973                                         ast_test_flag64(&user->userflags, CONFFLAG_MONITOR) ? "1" : "",
1974                                         user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED) ? "1" : "",
1975                                         user->adminflags & ADMINFLAG_T_REQUEST ? "1" : "",
1976                                         user->talking, hr, min, sec);
1977                         }
1978                         ao2_ref(user, -1);
1979                 }
1980                 ao2_iterator_destroy(&user_iter);
1981                 if (!concise) {
1982                         ast_cli(a->fd, "%d users in that conference.\n", cnf->users);
1983                 }
1984                 AST_LIST_UNLOCK(&confs);
1985                 return CLI_SUCCESS;
1986         }
1987         return CLI_SHOWUSAGE;
1988 }
1989
1990
1991 static char *meetme_cmd_helper(struct ast_cli_args *a)
1992 {
1993         /* Process the command */
1994         struct ast_str *cmdline;
1995
1996         /* Max confno length */
1997         if (!(cmdline = ast_str_create(MAX_CONFNUM))) {
1998                 return CLI_FAILURE;
1999         }
2000
2001         ast_str_set(&cmdline, 0, "%s", a->argv[2]);     /* Argv 2: conference number */
2002         if (strcasestr(a->argv[1], "lock")) {
2003                 if (strcasecmp(a->argv[1], "lock") == 0) {
2004                         /* Lock */
2005                         ast_str_append(&cmdline, 0, ",L");
2006                 } else {
2007                         /* Unlock */
2008                         ast_str_append(&cmdline, 0, ",l");
2009                 }
2010         } else if (strcasestr(a->argv[1], "mute")) { 
2011                 if (strcasecmp(a->argv[1], "mute") == 0) {
2012                         /* Mute */
2013                         if (strcasecmp(a->argv[3], "all") == 0) {
2014                                 ast_str_append(&cmdline, 0, ",N");
2015                         } else {
2016                                 ast_str_append(&cmdline, 0, ",M,%s", a->argv[3]);       
2017                         }
2018                 } else {
2019                         /* Unmute */
2020                         if (strcasecmp(a->argv[3], "all") == 0) {
2021                                 ast_str_append(&cmdline, 0, ",n");
2022                         } else {
2023                                 ast_str_append(&cmdline, 0, ",m,%s", a->argv[3]);
2024                         }
2025                 }
2026         } else if (strcasecmp(a->argv[1], "kick") == 0) {
2027                 if (strcasecmp(a->argv[3], "all") == 0) {
2028                         /* Kick all */
2029                         ast_str_append(&cmdline, 0, ",K");
2030                 } else {
2031                         /* Kick a single user */
2032                         ast_str_append(&cmdline, 0, ",k,%s", a->argv[3]);
2033                 }
2034         } else {
2035                 /*
2036                  * Should never get here because it is already filtered by the
2037                  * callers.
2038                  */
2039                 ast_free(cmdline);
2040                 return CLI_SHOWUSAGE;
2041         }
2042
2043         ast_debug(1, "Cmdline: %s\n", ast_str_buffer(cmdline));
2044
2045         admin_exec(NULL, ast_str_buffer(cmdline));
2046         ast_free(cmdline);
2047
2048         return CLI_SUCCESS;
2049 }
2050
2051 static char *meetme_lock_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2052 {
2053         switch (cmd) {
2054         case CLI_INIT:
2055                 e->command = "meetme {lock|unlock}";
2056                 e->usage =
2057                         "Usage: meetme lock|unlock <confno>\n"
2058                         "       Lock or unlock a conference to new users.\n";
2059                 return NULL;
2060         case CLI_GENERATE:
2061                 return complete_meetmecmd_lock(a->word, a->pos, a->n);
2062         }
2063
2064         if (a->argc != 3) {
2065                 return CLI_SHOWUSAGE;
2066         }
2067
2068         return meetme_cmd_helper(a);
2069 }
2070
2071 static char *meetme_kick_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2072 {
2073         switch (cmd) {
2074         case CLI_INIT:
2075                 e->command = "meetme kick";
2076                 e->usage =
2077                         "Usage: meetme kick <confno> all|<userno>\n"
2078                         "       Kick a conference or a user in a conference.\n";
2079                 return NULL;
2080         case CLI_GENERATE:
2081                 return complete_meetmecmd_mute_kick(a->line, a->word, a->pos, a->n);
2082         }
2083
2084         if (a->argc != 4) {
2085                 return CLI_SHOWUSAGE;
2086         }
2087
2088         return meetme_cmd_helper(a);
2089 }
2090
2091 static char *meetme_mute_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2092 {
2093         switch (cmd) {
2094         case CLI_INIT:
2095                 e->command = "meetme {mute|unmute}";
2096                 e->usage =
2097                         "Usage: meetme mute|unmute <confno> all|<userno>\n"
2098                         "       Mute or unmute a conference or a user in a conference.\n";
2099                 return NULL;
2100         case CLI_GENERATE:
2101                 return complete_meetmecmd_mute_kick(a->line, a->word, a->pos, a->n);
2102         }
2103
2104         if (a->argc != 4) {
2105                 return CLI_SHOWUSAGE;
2106         }
2107
2108         return meetme_cmd_helper(a);
2109 }
2110
2111 static const char *sla_hold_str(unsigned int hold_access)
2112 {
2113         const char *hold = "Unknown";
2114
2115         switch (hold_access) {
2116         case SLA_HOLD_OPEN:
2117                 hold = "Open";
2118                 break;
2119         case SLA_HOLD_PRIVATE:
2120                 hold = "Private";
2121         default:
2122                 break;
2123         }
2124
2125         return hold;
2126 }
2127
2128 static char *sla_show_trunks(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2129 {
2130         struct ao2_iterator i;
2131         struct sla_trunk *trunk;
2132
2133         switch (cmd) {
2134         case CLI_INIT:
2135                 e->command = "sla show trunks";
2136                 e->usage =
2137                         "Usage: sla show trunks\n"
2138                         "       This will list all trunks defined in sla.conf\n";
2139                 return NULL;
2140         case CLI_GENERATE:
2141                 return NULL;
2142         }
2143
2144         ast_cli(a->fd, "\n"
2145                     "=============================================================\n"
2146                     "=== Configured SLA Trunks ===================================\n"
2147                     "=============================================================\n"
2148                     "===\n");
2149         i = ao2_iterator_init(sla_trunks, 0);
2150         for (; (trunk = ao2_iterator_next(&i)); ao2_ref(trunk, -1)) {
2151                 struct sla_station_ref *station_ref;
2152                 char ring_timeout[16] = "(none)";
2153
2154                 ao2_lock(trunk);
2155
2156                 if (trunk->ring_timeout) {
2157                         snprintf(ring_timeout, sizeof(ring_timeout), "%u Seconds", trunk->ring_timeout);
2158                 }
2159
2160                 ast_cli(a->fd, "=== ---------------------------------------------------------\n"
2161                             "=== Trunk Name:       %s\n"
2162                             "=== ==> Device:       %s\n"
2163                             "=== ==> AutoContext:  %s\n"
2164                             "=== ==> RingTimeout:  %s\n"
2165                             "=== ==> BargeAllowed: %s\n"
2166                             "=== ==> HoldAccess:   %s\n"
2167                             "=== ==> Stations ...\n",
2168                             trunk->name, trunk->device, 
2169                             S_OR(trunk->autocontext, "(none)"), 
2170                             ring_timeout,
2171                             trunk->barge_disabled ? "No" : "Yes",
2172                             sla_hold_str(trunk->hold_access));
2173
2174                 AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) {
2175                         ast_cli(a->fd, "===    ==> Station name: %s\n", station_ref->station->name);
2176                 }
2177
2178                 ast_cli(a->fd, "=== ---------------------------------------------------------\n===\n");
2179
2180                 ao2_unlock(trunk);
2181         }
2182         ao2_iterator_destroy(&i);
2183         ast_cli(a->fd, "=============================================================\n\n");
2184
2185         return CLI_SUCCESS;
2186 }
2187
2188 static const char *trunkstate2str(enum sla_trunk_state state)
2189 {
2190 #define S(e) case e: return # e;
2191         switch (state) {
2192         S(SLA_TRUNK_STATE_IDLE)
2193         S(SLA_TRUNK_STATE_RINGING)
2194         S(SLA_TRUNK_STATE_UP)
2195         S(SLA_TRUNK_STATE_ONHOLD)
2196         S(SLA_TRUNK_STATE_ONHOLD_BYME)
2197         }
2198         return "Uknown State";
2199 #undef S
2200 }
2201
2202 static char *sla_show_stations(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2203 {
2204         struct ao2_iterator i;
2205         struct sla_station *station;
2206
2207         switch (cmd) {
2208         case CLI_INIT:
2209                 e->command = "sla show stations";
2210                 e->usage =
2211                         "Usage: sla show stations\n"
2212                         "       This will list all stations defined in sla.conf\n";
2213                 return NULL;
2214         case CLI_GENERATE:
2215                 return NULL;
2216         }
2217
2218         ast_cli(a->fd, "\n" 
2219                     "=============================================================\n"
2220                     "=== Configured SLA Stations =================================\n"
2221                     "=============================================================\n"
2222                     "===\n");
2223         i = ao2_iterator_init(sla_stations, 0);
2224         for (; (station = ao2_iterator_next(&i)); ao2_ref(station, -1)) {
2225                 struct sla_trunk_ref *trunk_ref;
2226                 char ring_timeout[16] = "(none)";
2227                 char ring_delay[16] = "(none)";
2228
2229                 ao2_lock(station);
2230
2231                 if (station->ring_timeout) {
2232                         snprintf(ring_timeout, sizeof(ring_timeout), 
2233                                 "%u", station->ring_timeout);
2234                 }
2235                 if (station->ring_delay) {
2236                         snprintf(ring_delay, sizeof(ring_delay), 
2237                                 "%u", station->ring_delay);
2238                 }
2239                 ast_cli(a->fd, "=== ---------------------------------------------------------\n"
2240                             "=== Station Name:    %s\n"
2241                             "=== ==> Device:      %s\n"
2242                             "=== ==> AutoContext: %s\n"
2243                             "=== ==> RingTimeout: %s\n"
2244                             "=== ==> RingDelay:   %s\n"
2245                             "=== ==> HoldAccess:  %s\n"
2246                             "=== ==> Trunks ...\n",
2247                             station->name, station->device,
2248                             S_OR(station->autocontext, "(none)"), 
2249                             ring_timeout, ring_delay,
2250                             sla_hold_str(station->hold_access));
2251                 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) {
2252                         if (trunk_ref->ring_timeout) {
2253                                 snprintf(ring_timeout, sizeof(ring_timeout),
2254                                         "%u", trunk_ref->ring_timeout);
2255                         } else
2256                                 strcpy(ring_timeout, "(none)");
2257                         if (trunk_ref->ring_delay) {
2258                                 snprintf(ring_delay, sizeof(ring_delay),
2259                                         "%u", trunk_ref->ring_delay);
2260                         } else
2261                                 strcpy(ring_delay, "(none)");
2262                                 ast_cli(a->fd, "===    ==> Trunk Name: %s\n"
2263                                     "===       ==> State:       %s\n"
2264                                     "===       ==> RingTimeout: %s\n"
2265                                     "===       ==> RingDelay:   %s\n",
2266                                     trunk_ref->trunk->name,
2267                                     trunkstate2str(trunk_ref->state),
2268                                     ring_timeout, ring_delay);
2269                 }
2270                 ast_cli(a->fd, "=== ---------------------------------------------------------\n"
2271                             "===\n");
2272
2273                 ao2_unlock(station);
2274         }
2275         ao2_iterator_destroy(&i);
2276         ast_cli(a->fd, "============================================================\n"
2277                     "\n");
2278
2279         return CLI_SUCCESS;
2280 }
2281
2282 static struct ast_cli_entry cli_meetme[] = {
2283         AST_CLI_DEFINE(meetme_kick_cmd, "Kick a conference or a user in a conference."),
2284         AST_CLI_DEFINE(meetme_show_cmd, "List all conferences or a specific conference."),
2285         AST_CLI_DEFINE(meetme_lock_cmd, "Lock or unlock a conference to new users."),
2286         AST_CLI_DEFINE(meetme_mute_cmd, "Mute or unmute a conference or a user in a conference."),
2287         AST_CLI_DEFINE(sla_show_trunks, "Show SLA Trunks"),
2288         AST_CLI_DEFINE(sla_show_stations, "Show SLA Stations"),
2289 };
2290
2291 static void conf_flush(int fd, struct ast_channel *chan)
2292 {
2293         int x;
2294
2295         /* read any frames that may be waiting on the channel
2296            and throw them away
2297         */
2298         if (chan) {
2299                 struct ast_frame *f;
2300
2301                 /* when no frames are available, this will wait
2302                    for 1 millisecond maximum
2303                 */
2304                 while (ast_waitfor(chan, 1) > 0) {
2305                         f = ast_read(chan);
2306                         if (f)
2307                                 ast_frfree(f);
2308                         else /* channel was hung up or something else happened */
2309                                 break;
2310                 }
2311         }
2312
2313         /* flush any data sitting in the pseudo channel */
2314         x = DAHDI_FLUSH_ALL;
2315         if (ioctl(fd, DAHDI_FLUSH, &x))
2316                 ast_log(LOG_WARNING, "Error flushing channel\n");
2317
2318 }
2319
2320 /*! \brief Remove the conference from the list and free it.
2321
2322    We assume that this was called while holding conflock. */
2323 static int conf_free(struct ast_conference *conf)
2324 {
2325         int x;
2326         struct announce_listitem *item;
2327
2328         AST_LIST_REMOVE(&confs, conf, list);
2329
2330         meetme_stasis_generate_msg(conf, NULL, NULL, meetme_end_type(), NULL);
2331
2332         if (conf->recording == MEETME_RECORD_ACTIVE) {
2333                 conf->recording = MEETME_RECORD_TERMINATE;
2334                 AST_LIST_UNLOCK(&confs);
2335                 while (1) {
2336                         usleep(1);
2337                         AST_LIST_LOCK(&confs);
2338                         if (conf->recording == MEETME_RECORD_OFF)
2339                                 break;
2340                         AST_LIST_UNLOCK(&confs);
2341                 }
2342         }
2343
2344         for (x = 0; x < AST_FRAME_BITS; x++) {
2345                 if (conf->transframe[x])
2346                         ast_frfree(conf->transframe[x]);
2347                 if (conf->transpath[x])
2348                         ast_translator_free_path(conf->transpath[x]);
2349         }
2350         if (conf->announcethread != AST_PTHREADT_NULL) {
2351                 ast_mutex_lock(&conf->announcelistlock);
2352                 conf->announcethread_stop = 1;
2353                 ast_softhangup(conf->chan, AST_SOFTHANGUP_EXPLICIT);
2354                 ast_cond_signal(&conf->announcelist_addition);
2355                 ast_mutex_unlock(&conf->announcelistlock);
2356                 pthread_join(conf->announcethread, NULL);
2357         
2358                 while ((item = AST_LIST_REMOVE_HEAD(&conf->announcelist, entry))) {
2359                         /* If it's a voicemail greeting file we don't want to remove it */
2360                         if (!item->vmrec){
2361                                 ast_filedelete(item->namerecloc, NULL);
2362                         }
2363                         ao2_ref(item, -1);
2364                 }
2365                 ast_mutex_destroy(&conf->announcelistlock);
2366         }
2367
2368         if (conf->origframe)
2369                 ast_frfree(conf->origframe);
2370         ast_hangup(conf->lchan);
2371         ast_hangup(conf->chan);
2372         if (conf->fd >= 0)
2373                 close(conf->fd);
2374         if (conf->recordingfilename) {
2375                 ast_free(conf->recordingfilename);
2376         }
2377         if (conf->usercontainer) {
2378                 ao2_ref(conf->usercontainer, -1);
2379         }
2380         if (conf->recordingformat) {
2381                 ast_free(conf->recordingformat);
2382         }
2383         ast_mutex_destroy(&conf->playlock);
2384         ast_mutex_destroy(&conf->listenlock);
2385         ast_mutex_destroy(&conf->recordthreadlock);
2386         ast_mutex_destroy(&conf->announcethreadlock);
2387         ast_free(conf);
2388
2389         return 0;
2390 }
2391
2392 static void conf_queue_dtmf(const struct ast_conference *conf,
2393         const struct ast_conf_user *sender, struct ast_frame *f)
2394 {
2395         struct ast_conf_user *user;
2396         struct ao2_iterator user_iter;
2397
2398         user_iter = ao2_iterator_init(conf->usercontainer, 0);
2399         while ((user = ao2_iterator_next(&user_iter))) {
2400                 if (user == sender) {
2401                         ao2_ref(user, -1);
2402                         continue;
2403                 }
2404                 if (ast_write(user->chan, f) < 0)
2405                         ast_log(LOG_WARNING, "Error writing frame to channel %s\n", ast_channel_name(user->chan));
2406                 ao2_ref(user, -1);
2407         }
2408         ao2_iterator_destroy(&user_iter);
2409 }
2410
2411 static void sla_queue_event_full(enum sla_event_type type, 
2412         struct sla_trunk_ref *trunk_ref, struct sla_station *station, int lock)
2413 {
2414         struct sla_event *event;
2415
2416         if (sla.thread == AST_PTHREADT_NULL) {
2417                 ao2_ref(station, -1);
2418                 ao2_ref(trunk_ref, -1);
2419                 return;
2420         }
2421
2422         if (!(event = ast_calloc(1, sizeof(*event)))) {
2423                 ao2_ref(station, -1);
2424                 ao2_ref(trunk_ref, -1);
2425                 return;
2426         }
2427
2428         event->type = type;
2429         event->trunk_ref = trunk_ref;
2430         event->station = station;
2431
2432         if (!lock) {
2433                 AST_LIST_INSERT_TAIL(&sla.event_q, event, entry);
2434                 return;
2435         }
2436
2437         ast_mutex_lock(&sla.lock);
2438         AST_LIST_INSERT_TAIL(&sla.event_q, event, entry);
2439         ast_cond_signal(&sla.cond);
2440         ast_mutex_unlock(&sla.lock);
2441 }
2442
2443 static void sla_queue_event_nolock(enum sla_event_type type)
2444 {
2445         sla_queue_event_full(type, NULL, NULL, 0);
2446 }
2447
2448 static void sla_queue_event(enum sla_event_type type)
2449 {
2450         sla_queue_event_full(type, NULL, NULL, 1);
2451 }
2452
2453 /*! \brief Queue a SLA event from the conference */
2454 static void sla_queue_event_conf(enum sla_event_type type, struct ast_channel *chan,
2455         struct ast_conference *conf)
2456 {
2457         struct sla_station *station;
2458         struct sla_trunk_ref *trunk_ref = NULL;
2459         char *trunk_name;
2460         struct ao2_iterator i;
2461
2462         trunk_name = ast_strdupa(conf->confno);
2463         strsep(&trunk_name, "_");
2464         if (ast_strlen_zero(trunk_name)) {
2465                 ast_log(LOG_ERROR, "Invalid conference name for SLA - '%s'!\n", conf->confno);
2466                 return;
2467         }
2468
2469         i = ao2_iterator_init(sla_stations, 0);
2470         while ((station = ao2_iterator_next(&i))) {
2471                 ao2_lock(station);
2472                 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) {
2473                         if (trunk_ref->chan == chan && !strcmp(trunk_ref->trunk->name, trunk_name)) {
2474                                 ao2_ref(trunk_ref, 1);
2475                                 break;
2476                         }
2477                 }
2478                 ao2_unlock(station);
2479                 if (trunk_ref) {
2480                         /* station reference given to sla_queue_event_full() */
2481                         break;
2482                 }
2483                 ao2_ref(station, -1);
2484         }
2485         ao2_iterator_destroy(&i);
2486
2487         if (!trunk_ref) {
2488                 ast_debug(1, "Trunk not found for event!\n");
2489                 return;
2490         }
2491
2492         sla_queue_event_full(type, trunk_ref, station, 1);
2493 }
2494
2495 /*! \brief Decrement reference counts, as incremented by find_conf() */
2496 static int dispose_conf(struct ast_conference *conf)
2497 {
2498         int res = 0;
2499         int confno_int = 0;
2500
2501         AST_LIST_LOCK(&confs);
2502         if (ast_atomic_dec_and_test(&conf->refcount)) {
2503                 /* Take the conference room number out of an inuse state */
2504                 if ((sscanf(conf->confno, "%4d", &confno_int) == 1) && (confno_int >= 0 && confno_int < 1024)) {
2505                         conf_map[confno_int] = 0;
2506                 }
2507                 conf_free(conf);
2508                 res = 1;
2509         }
2510         AST_LIST_UNLOCK(&confs);
2511
2512         return res;
2513 }
2514
2515 static int rt_extend_conf(const char *confno)
2516 {
2517         char currenttime[32];
2518         char endtime[32];
2519         struct timeval now;
2520         struct ast_tm tm;
2521         struct ast_variable *var, *orig_var;
2522         char bookid[51];
2523
2524         if (!extendby) {
2525                 return 0;
2526         }
2527
2528         now = ast_tvnow();
2529
2530         ast_localtime(&now, &tm, NULL);
2531         ast_strftime(currenttime, sizeof(currenttime), DATE_FORMAT, &tm);
2532
2533         var = ast_load_realtime("meetme", "confno",
2534                 confno, "startTime<= ", currenttime,
2535                 "endtime>= ", currenttime, NULL);
2536
2537         orig_var = var;
2538
2539         /* Identify the specific RealTime conference */
2540         while (var) {
2541                 if (!strcasecmp(var->name, "bookid")) {
2542                         ast_copy_string(bookid, var->value, sizeof(bookid));
2543                 }
2544                 if (!strcasecmp(var->name, "endtime")) {
2545                         ast_copy_string(endtime, var->value, sizeof(endtime));
2546                 }
2547
2548                 var = var->next;
2549         }
2550         ast_variables_destroy(orig_var);
2551
2552         ast_strptime(endtime, DATE_FORMAT, &tm);
2553         now = ast_mktime(&tm, NULL);
2554
2555         now.tv_sec += extendby;
2556
2557         ast_localtime(&now, &tm, NULL);
2558         ast_strftime(currenttime, sizeof(currenttime), DATE_FORMAT, &tm);
2559         strcat(currenttime, "0"); /* Seconds needs to be 00 */
2560
2561         var = ast_load_realtime("meetme", "confno",
2562                 confno, "startTime<= ", currenttime,
2563                 "endtime>= ", currenttime, NULL);
2564
2565         /* If there is no conflict with extending the conference, update the DB */
2566         if (!var) {
2567                 ast_debug(3, "Trying to update the endtime of Conference %s to %s\n", confno, currenttime);
2568                 ast_update_realtime("meetme", "bookid", bookid, "endtime", currenttime, NULL);
2569                 return 0;
2570
2571         }
2572
2573         ast_variables_destroy(var);
2574         return -1;
2575 }
2576
2577 static void conf_start_moh(struct ast_channel *chan, const char *musicclass)
2578 {
2579         char *original_moh;
2580
2581         ast_channel_lock(chan);
2582         original_moh = ast_strdupa(ast_channel_musicclass(chan));
2583         ast_channel_musicclass_set(chan, musicclass);
2584         ast_channel_unlock(chan);
2585
2586         ast_moh_start(chan, original_moh, NULL);
2587
2588         ast_channel_lock(chan);
2589         ast_channel_musicclass_set(chan, original_moh);
2590         ast_channel_unlock(chan);
2591 }
2592
2593 static const char *get_announce_filename(enum announcetypes type)
2594 {
2595         switch (type) {
2596         case CONF_HASLEFT:
2597                 return "conf-hasleft";
2598                 break;
2599         case CONF_HASJOIN:
2600                 return "conf-hasjoin";
2601                 break;
2602         default:
2603                 return "";
2604         }
2605 }
2606
2607 static void *announce_thread(void *data)
2608 {
2609         struct announce_listitem *current;
2610         struct ast_conference *conf = data;
2611         int res;
2612         char filename[PATH_MAX] = "";
2613         AST_LIST_HEAD_NOLOCK(, announce_listitem) local_list;
2614         AST_LIST_HEAD_INIT_NOLOCK(&local_list);
2615
2616         while (!conf->announcethread_stop) {
2617                 ast_mutex_lock(&conf->announcelistlock);
2618                 if (conf->announcethread_stop) {
2619                         ast_mutex_unlock(&conf->announcelistlock);
2620                         break;
2621                 }
2622                 if (AST_LIST_EMPTY(&conf->announcelist))
2623                         ast_cond_wait(&conf->announcelist_addition, &conf->announcelistlock);
2624
2625                 AST_LIST_APPEND_LIST(&local_list, &conf->announcelist, entry);
2626                 AST_LIST_HEAD_INIT_NOLOCK(&conf->announcelist);
2627
2628                 ast_mutex_unlock(&conf->announcelistlock);
2629                 if (conf->announcethread_stop) {
2630                         break;
2631                 }
2632
2633                 for (res = 1; !conf->announcethread_stop && (current = AST_LIST_REMOVE_HEAD(&local_list, entry)); ao2_ref(current, -1)) {
2634                         ast_debug(1, "About to play %s\n", current->namerecloc);
2635                         if (!ast_fileexists(current->namerecloc, NULL, NULL))
2636                                 continue;
2637                         if ((current->confchan) && (current->confusers > 1) && !ast_check_hangup(current->confchan)) {
2638                                 if (!ast_streamfile(current->confchan, current->namerecloc, current->language))
2639                                         res = ast_waitstream(current->confchan, "");
2640                                 if (!res) {
2641                                         ast_copy_string(filename, get_announce_filename(current->announcetype), sizeof(filename));
2642                                         if (!ast_streamfile(current->confchan, filename, current->language))
2643                                                 ast_waitstream(current->confchan, "");
2644                                 }
2645                         }
2646                         if (current->announcetype == CONF_HASLEFT && current->announcetype && !current->vmrec) {
2647                                 /* only remove it if it isn't a VM recording file */
2648                                 ast_filedelete(current->namerecloc, NULL);
2649                         }
2650                 }
2651         }
2652
2653         /* thread marked to stop, clean up */
2654         while ((current = AST_LIST_REMOVE_HEAD(&local_list, entry))) {
2655                 /* only delete if it's a vm rec */
2656                 if (!current->vmrec) {
2657                         ast_filedelete(current->namerecloc, NULL);
2658                 }
2659                 ao2_ref(current, -1);
2660         }
2661         return NULL;
2662 }
2663
2664 static int can_write(struct ast_channel *chan, struct ast_flags64 *confflags)
2665 {
2666         if (!ast_test_flag64(confflags, CONFFLAG_NO_AUDIO_UNTIL_UP)) {
2667                 return 1;
2668         }
2669
2670         return (ast_channel_state(chan) == AST_STATE_UP);
2671 }
2672
2673 static void send_talking_event(struct ast_channel *chan, struct ast_conference *conf, struct ast_conf_user *user, int talking)
2674 {
2675         RAII_VAR(struct ast_json *, status_blob, status_to_json(talking), ast_json_unref);
2676         meetme_stasis_generate_msg(conf, chan, user, meetme_talking_type(), status_blob);
2677 }
2678
2679 static void set_user_talking(struct ast_channel *chan, struct ast_conference *conf, struct ast_conf_user *user, int talking, int monitor)
2680 {
2681         int last_talking = user->talking;
2682         if (last_talking == talking)
2683                 return;
2684
2685         user->talking = talking;
2686
2687         if (monitor) {
2688                 /* Check if talking state changed. Take care of -1 which means unmonitored */
2689                 int was_talking = (last_talking > 0);
2690                 int now_talking = (talking > 0);
2691                 if (was_talking != now_talking) {
2692                         send_talking_event(chan, conf, user, now_talking);
2693                 }
2694         }
2695 }
2696
2697 static int user_set_hangup_cb(void *obj, void *check_admin_arg, int flags)
2698 {
2699         struct ast_conf_user *user = obj;
2700         /* actual pointer contents of check_admin_arg is irrelevant */
2701
2702         if (!check_admin_arg || (check_admin_arg && !ast_test_flag64(&user->userflags, CONFFLAG_ADMIN))) {
2703                 user->adminflags |= ADMINFLAG_HANGUP;
2704         }
2705         return 0;
2706 }
2707
2708 static int user_set_kickme_cb(void *obj, void *check_admin_arg, int flags)
2709 {
2710         struct ast_conf_user *user = obj;
2711         /* actual pointer contents of check_admin_arg is irrelevant */
2712
2713         if (!check_admin_arg || (check_admin_arg && !ast_test_flag64(&user->userflags, CONFFLAG_ADMIN))) {
2714                 user->adminflags |= ADMINFLAG_KICKME;
2715         }
2716         return 0;
2717 }
2718
2719 static int user_set_unmuted_cb(void *obj, void *check_admin_arg, int flags)
2720 {
2721         struct ast_conf_user *user = obj;
2722         /* actual pointer contents of check_admin_arg is irrelevant */
2723
2724         if (!check_admin_arg || !ast_test_flag64(&user->userflags, CONFFLAG_ADMIN)) {
2725                 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED | ADMINFLAG_T_REQUEST);
2726         }
2727         return 0;
2728 }
2729
2730 static int user_set_muted_cb(void *obj, void *check_admin_arg, int flags)
2731 {
2732         struct ast_conf_user *user = obj;
2733         /* actual pointer contents of check_admin_arg is irrelevant */
2734
2735         if (!check_admin_arg || !ast_test_flag64(&user->userflags, CONFFLAG_ADMIN)) {
2736                 user->adminflags |= ADMINFLAG_MUTED;
2737         }
2738         return 0;
2739 }
2740
2741 enum menu_modes {
2742         MENU_DISABLED = 0,
2743         MENU_NORMAL,
2744         MENU_ADMIN,
2745         MENU_ADMIN_EXTENDED,
2746 };
2747
2748 /*! \internal
2749  * \brief Processes menu options for the standard menu (accessible through the 's' option for app_meetme)
2750  *
2751  * \param menu_mode a pointer to the currently active menu_mode.
2752  * \param dtmf a pointer to the dtmf value currently being processed against the menu.
2753  * \param conf the active conference for which the user has called the menu from.
2754  * \param confflags flags used by conf for various options
2755  * \param chan ast_channel belonging to the user who called the menu
2756  * \param user which meetme conference user invoked the menu
2757  */
2758 static void meetme_menu_normal(enum menu_modes *menu_mode, int *dtmf, struct ast_conference *conf, struct ast_flags64 *confflags, struct ast_channel *chan, struct ast_conf_user *user)
2759 {
2760         switch (*dtmf) {
2761         case '1': /* Un/Mute */
2762                 *menu_mode = MENU_DISABLED;
2763
2764                 /* user can only toggle the self-muted state */
2765                 user->adminflags ^= ADMINFLAG_SELFMUTED;
2766
2767                 /* they can't override the admin mute state */
2768                 if (ast_test_flag64(confflags, CONFFLAG_MONITOR) || (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED))) {
2769                         if (!ast_streamfile(chan, "conf-muted", ast_channel_language(chan))) {
2770                                 ast_waitstream(chan, "");
2771                         }
2772                 } else {
2773                         if (!ast_streamfile(chan, "conf-unmuted", ast_channel_language(chan))) {
2774                                 ast_waitstream(chan, "");
2775                         }
2776                 }
2777                 break;
2778
2779         case '2':
2780                 *menu_mode = MENU_DISABLED;
2781                 if (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) {
2782                         user->adminflags |= ADMINFLAG_T_REQUEST;
2783                 }
2784
2785                 if (user->adminflags & ADMINFLAG_T_REQUEST) {
2786                         if (!ast_streamfile(chan, "beep", ast_channel_language(chan))) {
2787                                 ast_waitstream(chan, "");
2788                         }
2789                 }
2790                 break;
2791
2792         case '4':
2793                 tweak_listen_volume(user, VOL_DOWN);
2794                 break;
2795         case '5':
2796                 /* Extend RT conference */
2797                 if (rt_schedule) {
2798                         rt_extend_conf(conf->confno);
2799                 }
2800                 *menu_mode = MENU_DISABLED;
2801                 break;
2802
2803         case '6':
2804                 tweak_listen_volume(user, VOL_UP);
2805                 break;
2806
2807         case '7':
2808                 tweak_talk_volume(user, VOL_DOWN);
2809                 break;
2810
2811         case '8':
2812                 *menu_mode = MENU_DISABLED;
2813                 break;
2814
2815         case '9':
2816                 tweak_talk_volume(user, VOL_UP);
2817                 break;
2818
2819         default:
2820                 *menu_mode = MENU_DISABLED;
2821                 if (!ast_streamfile(chan, "conf-errormenu", ast_channel_language(chan))) {
2822                         ast_waitstream(chan, "");
2823                 }
2824                 break;
2825         }
2826 }
2827
2828 /*! \internal
2829  * \brief Processes menu options for the adminstrator menu (accessible through the 's' option for app_meetme)
2830  *
2831  * \param menu_mode a pointer to the currently active menu_mode.
2832  * \param dtmf a pointer to the dtmf value currently being processed against the menu.
2833  * \param conf the active conference for which the user has called the menu from.
2834  * \param confflags flags used by conf for various options
2835  * \param chan ast_channel belonging to the user who called the menu
2836  * \param user which meetme conference user invoked the menu
2837  */
2838 static void meetme_menu_admin(enum menu_modes *menu_mode, int *dtmf, struct ast_conference *conf, struct ast_flags64 *confflags, struct ast_channel *chan, struct ast_conf_user *user)
2839 {
2840         switch(*dtmf) {
2841         case '1': /* Un/Mute */
2842                 *menu_mode = MENU_DISABLED;
2843                 /* for admin, change both admin and use flags */
2844                 if (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) {
2845                         user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED);
2846                 } else {
2847                         user->adminflags |= (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED);
2848                 }
2849
2850                 if (ast_test_flag64(confflags, CONFFLAG_MONITOR) || (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED))) {
2851                         if (!ast_streamfile(chan, "conf-muted", ast_channel_language(chan))) {
2852                                 ast_waitstream(chan, "");
2853                         }
2854                 } else {
2855                         if (!ast_streamfile(chan, "conf-unmuted", ast_channel_language(chan))) {
2856                                 ast_waitstream(chan, "");
2857                         }
2858                 }
2859                 break;
2860
2861         case '2': /* Un/Lock the Conference */
2862                 *menu_mode = MENU_DISABLED;
2863                 if (conf->locked) {
2864                         conf->locked = 0;
2865                         if (!ast_streamfile(chan, "conf-unlockednow", ast_channel_language(chan))) {
2866                                 ast_waitstream(chan, "");
2867                         }
2868                 } else {
2869                         conf->locked = 1;
2870                         if (!ast_streamfile(chan, "conf-lockednow", ast_channel_language(chan))) {
2871                                 ast_waitstream(chan, "");
2872                         }
2873                 }
2874                 break;
2875
2876         case '3': /* Eject last user */
2877         {
2878                 struct ast_conf_user *usr = NULL;
2879                 int max_no = 0;
2880                 ao2_callback(conf->usercontainer, OBJ_NODATA, user_max_cmp, &max_no);
2881                 *menu_mode = MENU_DISABLED;
2882                 usr = ao2_find(conf->usercontainer, &max_no, 0);
2883                 if ((ast_channel_name(usr->chan) == ast_channel_name(chan)) || ast_test_flag64(&usr->userflags, CONFFLAG_ADMIN)) {
2884                         if (!ast_streamfile(chan, "conf-errormenu", ast_channel_language(chan))) {
2885                                 ast_waitstream(chan, "");
2886                         }
2887                 } else {
2888                         usr->adminflags |= ADMINFLAG_KICKME;
2889                 }
2890                 ao2_ref(usr, -1);
2891                 ast_stopstream(chan);
2892                 break;
2893         }
2894
2895         case '4':
2896                 tweak_listen_volume(user, VOL_DOWN);
2897                 break;
2898
2899         case '5':
2900                 /* Extend RT conference */
2901                 if (rt_schedule) {
2902                         if (!rt_extend_conf(conf->confno)) {
2903                                 if (!ast_streamfile(chan, "conf-extended", ast_channel_language(chan))) {
2904                                         ast_waitstream(chan, "");
2905                                 }
2906                         } else {
2907                                 if (!ast_streamfile(chan, "conf-nonextended", ast_channel_language(chan))) {
2908                                         ast_waitstream(chan, "");
2909                                 }
2910                         }
2911                         ast_stopstream(chan);
2912                 }
2913                 *menu_mode = MENU_DISABLED;
2914                 break;
2915
2916         case '6':
2917                 tweak_listen_volume(user, VOL_UP);
2918                 break;
2919
2920         case '7':
2921                 tweak_talk_volume(user, VOL_DOWN);
2922                 break;
2923
2924         case '8':
2925                 if (!ast_streamfile(chan, "conf-adminmenu-menu8", ast_channel_language(chan))) {
2926                         /* If the user provides DTMF while playing the sound, we want to drop right into the extended menu function with new DTMF once we get out of here. */
2927                         *dtmf = ast_waitstream(chan, AST_DIGIT_ANY);
2928                         ast_stopstream(chan);
2929                 }
2930                 *menu_mode = MENU_ADMIN_EXTENDED;
2931                 break;
2932
2933         case '9':
2934                 tweak_talk_volume(user, VOL_UP);
2935                 break;
2936         default:
2937                 *menu_mode = MENU_DISABLED;
2938                 /* Play an error message! */
2939                 if (!ast_streamfile(chan, "conf-errormenu", ast_channel_language(chan))) {
2940                         ast_waitstream(chan, "");
2941                 }
2942                 break;
2943         }
2944
2945 }
2946
2947 /*! \internal
2948  * \brief Processes menu options for the extended administrator menu (accessible through option 8 on the administrator menu)
2949  *
2950  * \param menu_mode a pointer to the currently active menu_mode.
2951  * \param dtmf a pointer to the dtmf value currently being processed against the menu.
2952  * \param conf the active conference for which the user has called the menu from.
2953  * \param confflags flags used by conf for various options
2954  * \param chan ast_channel belonging to the user who called the menu
2955  * \param user which meetme conference user invoked the menu
2956  * \param recordingtmp character buffer which may hold the name of the conference recording file
2957  */
2958 static void meetme_menu_admin_extended(enum menu_modes *menu_mode, int *dtmf,
2959         struct ast_conference *conf, struct ast_flags64 *confflags, struct ast_channel *chan,
2960         struct ast_conf_user *user, char *recordingtmp, int recordingtmp_size,
2961         struct ast_format_cap *cap_slin)
2962 {
2963         int keepplaying;
2964         int playednamerec;
2965         int res;
2966         struct ao2_iterator user_iter;
2967         struct ast_conf_user *usr = NULL;
2968
2969         switch(*dtmf) {
2970         case '1': /* *81 Roll call */
2971                 keepplaying = 1;
2972                 playednamerec = 0;
2973                 if (conf->users == 1) {
2974                         if (keepplaying && !ast_streamfile(chan, "conf-onlyperson", ast_channel_language(chan))) {
2975                                 res = ast_waitstream(chan, AST_DIGIT_ANY);
2976                                 ast_stopstream(chan);
2977                                 if (res > 0) {
2978                                         keepplaying = 0;
2979                                 }
2980                         }
2981                 } else if (conf->users == 2) {
2982                         if (keepplaying && !ast_streamfile(chan, "conf-onlyone", ast_channel_language(chan))) {
2983                                 res = ast_waitstream(chan, AST_DIGIT_ANY);
2984                                 ast_stopstream(chan);
2985                                 if (res > 0) {
2986                                         keepplaying = 0;
2987                                 }
2988                         }
2989                 } else {
2990                         if (keepplaying && !ast_streamfile(chan, "conf-thereare", ast_channel_language(chan))) {
2991                                 res = ast_waitstream(chan, AST_DIGIT_ANY);
2992                                 ast_stopstream(chan);
2993                                 if (res > 0) {
2994                                         keepplaying = 0;
2995                                 }
2996                         }
2997                         if (keepplaying) {
2998                                 res = ast_say_number(chan, conf->users - 1, AST_DIGIT_ANY, ast_channel_language(chan), (char *) NULL);
2999                                 ast_stopstream(chan);
3000                                 if (res > 0) {
3001                                         keepplaying = 0;
3002                                 }
3003                         }
3004                         if (keepplaying && !ast_streamfile(chan, "conf-otherinparty", ast_channel_language(chan))) {
3005                                 res = ast_waitstream(chan, AST_DIGIT_ANY);
3006                                 ast_stopstream(chan);
3007                                 if (res > 0) {
3008                                         keepplaying = 0;
3009                                 }
3010                         }
3011                 }
3012                 user_iter = ao2_iterator_init(conf->usercontainer, 0);
3013                 while((usr = ao2_iterator_next(&user_iter))) {
3014                         if (ast_fileexists(usr->namerecloc, NULL, NULL)) {
3015                                 if (keepplaying && !ast_streamfile(chan, usr->namerecloc, ast_channel_language(chan))) {
3016                                         res = ast_waitstream(chan, AST_DIGIT_ANY);
3017                                         ast_stopstream(chan);
3018                                         if (res > 0) {
3019                                                 keepplaying = 0;
3020                                         }
3021                                 }
3022                                 playednamerec = 1;
3023                         }
3024                         ao2_ref(usr, -1);
3025                 }
3026                 ao2_iterator_destroy(&user_iter);
3027                 if (keepplaying && playednamerec && !ast_streamfile(chan, "conf-roll-callcomplete", ast_channel_language(chan))) {
3028                         res = ast_waitstream(chan, AST_DIGIT_ANY);
3029                         ast_stopstream(chan);
3030                         if (res > 0) {
3031                                 keepplaying = 0;
3032                         }
3033                 }
3034
3035                 *menu_mode = MENU_DISABLED;
3036                 break;
3037
3038         case '2': /* *82 Eject all non-admins */
3039                 if (conf->users == 1) {
3040                         if(!ast_streamfile(chan, "conf-errormenu", ast_channel_language(chan))) {
3041                                 ast_waitstream(chan, "");
3042                         }
3043                 } else {
3044                         ao2_callback(conf->usercontainer, OBJ_NODATA, user_set_kickme_cb, &conf);
3045                 }
3046                 ast_stopstream(chan);
3047                 *menu_mode = MENU_DISABLED;
3048                 break;
3049
3050         case '3': /* *83 (Admin) mute/unmute all non-admins */
3051                 if(conf->gmuted) {
3052                         conf->gmuted = 0;
3053                         ao2_callback(conf->usercontainer, OBJ_NODATA, user_set_unmuted_cb, &conf);
3054                         if (!ast_streamfile(chan, "conf-now-unmuted", ast_channel_language(chan))) {
3055                                 ast_waitstream(chan, "");
3056                         }
3057                 } else {
3058                         conf->gmuted = 1;
3059                         ao2_callback(conf->usercontainer, OBJ_NODATA, user_set_muted_cb, &conf);
3060                         if (!ast_streamfile(chan, "conf-now-muted", ast_channel_language(chan))) {
3061                                 ast_waitstream(chan, "");
3062                         }
3063                 }
3064                 ast_stopstream(chan);
3065                 *menu_mode = MENU_DISABLED;
3066                 break;
3067
3068         case '4': /* *84 Record conference */
3069                 if (conf->recording != MEETME_RECORD_ACTIVE) {
3070                         ast_set_flag64(confflags, CONFFLAG_RECORDCONF);
3071                         if (!conf->recordingfilename) {
3072                                 const char *var;
3073                                 ast_channel_lock(chan);
3074                                 if ((var = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFILE"))) {
3075                                         conf->recordingfilename = ast_strdup(var);
3076                                 }
3077                                 if ((var = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFORMAT"))) {
3078                                         conf->recordingformat = ast_strdup(var);
3079                                 }
3080                                 ast_channel_unlock(chan);
3081                                 if (!conf->recordingfilename) {
3082                                         snprintf(recordingtmp, recordingtmp_size, "meetme-conf-rec-%s-%s", conf->confno, ast_channel_uniqueid(chan));
3083                                         conf->recordingfilename = ast_strdup(recordingtmp);
3084                                 }
3085                                 if (!conf->recordingformat) {
3086                                         conf->recordingformat = ast_strdup("wav");
3087                                 }
3088                                 ast_verb(4, "Starting recording of MeetMe Conference %s into file %s.%s.\n",
3089                                 conf->confno, conf->recordingfilename, conf->recordingformat);
3090                         }
3091
3092                         ast_mutex_lock(&conf->recordthreadlock);
3093                         if ((conf->recordthread == AST_PTHREADT_NULL) && ast_test_flag64(confflags, CONFFLAG_RECORDCONF) && ((conf->lchan = ast_request("DAHDI", cap_slin, NULL, chan, "pseudo", NULL)))) {
3094                                 struct dahdi_confinfo dahdic;
3095
3096                                 ast_set_read_format(conf->lchan, ast_format_slin);
3097                                 ast_set_write_format(conf->lchan, ast_format_slin);
3098                                 dahdic.chan = 0;
3099                                 dahdic.confno = conf->dahdiconf;
3100                                 dahdic.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON;
3101                                 if (ioctl(ast_channel_fd(conf->lchan, 0), DAHDI_SETCONF, &dahdic)) {
3102                                         ast_log(LOG_WARNING, "Error starting listen channel\n");
3103                                         ast_hangup(conf->lchan);
3104                                         conf->lchan = NULL;
3105                                 } else {
3106                                         ast_pthread_create_detached_background(&conf->recordthread, NULL, recordthread, conf);
3107                                 }
3108                         }
3109                         ast_mutex_unlock(&conf->recordthreadlock);
3110                         if (!ast_streamfile(chan, "conf-now-recording", ast_channel_language(chan))) {
3111                                 ast_waitstream(chan, "");
3112                         }
3113                 }
3114
3115                 ast_stopstream(chan);
3116                 *menu_mode = MENU_DISABLED;
3117                 break;
3118
3119         case '8': /* *88 Exit the menu and return to the conference... without an error message */
3120                 ast_stopstream(chan);
3121                 *menu_mode = MENU_DISABLED;
3122                 break;
3123
3124         default:
3125                 if (!ast_streamfile(chan, "conf-errormenu", ast_channel_language(chan))) {
3126                         ast_waitstream(chan, "");
3127                 }
3128                 ast_stopstream(chan);
3129                 *menu_mode = MENU_DISABLED;
3130                 break;
3131         }
3132 }
3133
3134 /*! \internal
3135  * \brief Processes menu options for the various menu types (accessible through the 's' option for app_meetme)
3136  *
3137  * \param menu_mode a pointer to the currently active menu_mode.
3138  * \param dtmf a pointer to the dtmf value currently being processed against the menu.
3139  * \param conf the active conference for which the user has called the menu from.
3140  * \param confflags flags used by conf for various options
3141  * \param chan ast_channel belonging to the user who called the menu
3142  * \param user which meetme conference user invoked the menu
3143  * \param recordingtmp character buffer which may hold the name of the conference recording file
3144  */
3145 static void meetme_menu(enum menu_modes *menu_mode, int *dtmf,
3146         struct ast_conference *conf, struct ast_flags64 *confflags, struct ast_channel *chan,
3147         struct ast_conf_user *user, char *recordingtmp, int recordingtmp_size,
3148         struct ast_format_cap *cap_slin)
3149 {
3150         switch (*menu_mode) {
3151         case MENU_DISABLED:
3152                 break;
3153         case MENU_NORMAL:
3154                 meetme_menu_normal(menu_mode, dtmf, conf, confflags, chan, user);
3155                 break;
3156         case MENU_ADMIN:
3157                 meetme_menu_admin(menu_mode, dtmf, conf, confflags, chan, user);
3158                 /* Admin Menu is capable of branching into another menu, in which case it will reset dtmf and change the menu mode. */
3159                 if (*menu_mode != MENU_ADMIN_EXTENDED || (*dtmf <= 0)) {
3160                         break;
3161                 }
3162         case MENU_ADMIN_EXTENDED:
3163                 meetme_menu_admin_extended(menu_mode, dtmf, conf, confflags, chan, user,
3164                         recordingtmp, recordingtmp_size, cap_slin);
3165                 break;
3166         }
3167 }
3168
3169 static int conf_run(struct ast_channel *chan, struct ast_conference *conf, struct ast_flags64 *confflags, char *optargs[])
3170 {
3171         struct ast_conf_user *user = NULL;
3172         int fd;
3173         struct dahdi_confinfo dahdic, dahdic_empty;
3174         struct ast_frame *f;
3175         struct ast_channel *c;
3176         struct ast_frame fr;
3177         int outfd;
3178         int ms;
3179         int nfds;
3180         int res;
3181         int retrydahdi;
3182         int origfd;
3183         int musiconhold = 0, mohtempstopped = 0;
3184         int firstpass = 0;
3185         int lastmarked = 0;
3186         int currentmarked = 0;
3187         int ret = -1;
3188         int x;
3189         enum menu_modes menu_mode = MENU_DISABLED;
3190         int talkreq_manager = 0;
3191         int using_pseudo = 0;
3192         int duration = 20;
3193         int sent_event = 0;
3194         int checked = 0;
3195         int announcement_played = 0;
3196         struct timeval now;
3197         struct ast_dsp *dsp = NULL;
3198         struct ast_app *agi_app;
3199         char *agifile, *mod_speex;
3200         const char *agifiledefault = "conf-background.agi", *tmpvar;
3201         char meetmesecs[30] = "";
3202         char exitcontext[AST_MAX_CONTEXT] = "";
3203         char recordingtmp[AST_MAX_EXTENSION] = "";
3204         char members[10] = "";
3205         int dtmf = 0, opt_waitmarked_timeout = 0;
3206         time_t timeout = 0;
3207         struct dahdi_bufferinfo bi;
3208         char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET];
3209         char *buf = __buf + AST_FRIENDLY_OFFSET;
3210         char *exitkeys = NULL;
3211         unsigned int calldurationlimit = 0;
3212         long timelimit = 0;
3213         long play_warning = 0;
3214         long warning_freq = 0;
3215         const char *warning_sound = NULL;
3216         const char *end_sound = NULL;
3217         char *parse;
3218         long time_left_ms = 0;
3219         struct timeval nexteventts = { 0, };
3220         int to;
3221         int setusercount = 0;
3222         int confsilence = 0, totalsilence = 0;
3223         char *mailbox, *context;
3224         struct ast_format_cap *cap_slin = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
3225
3226         if (!cap_slin) {
3227                 goto conf_run_cleanup;
3228         }
3229         ast_format_cap_append(cap_slin, ast_format_slin, 0);
3230
3231         if (!(user = ao2_alloc(sizeof(*user), NULL))) {
3232                 goto conf_run_cleanup;
3233         }
3234
3235         /* Possible timeout waiting for marked user */
3236         if (ast_test_flag64(confflags, CONFFLAG_WAITMARKED) &&
3237                 !ast_strlen_zero(optargs[OPT_ARG_WAITMARKED]) &&
3238                 (sscanf(optargs[OPT_ARG_WAITMARKED], "%30d", &opt_waitmarked_timeout) == 1) &&
3239                 (opt_waitmarked_timeout > 0)) {
3240                 timeout = time(NULL) + opt_waitmarked_timeout;
3241         }
3242
3243         if (ast_test_flag64(confflags, CONFFLAG_DURATION_STOP) && !ast_strlen_zero(optargs[OPT_ARG_DURATION_STOP])) {
3244                 calldurationlimit = atoi(optargs[OPT_ARG_DURATION_STOP]);
3245                 ast_verb(3, "Setting call duration limit to %u seconds.\n", calldurationlimit);
3246         }
3247
3248         if (ast_test_flag64(confflags, CONFFLAG_DURATION_LIMIT) && !ast_strlen_zero(optargs[OPT_ARG_DURATION_LIMIT])) {
3249                 char *limit_str, *warning_str, *warnfreq_str;
3250                 const char *var;
3251
3252                 parse = optargs[OPT_ARG_DURATION_LIMIT];
3253                 limit_str = strsep(&parse, ":");
3254                 warning_str = strsep(&parse, ":");
3255                 warnfreq_str = parse;
3256
3257                 timelimit = atol(limit_str);
3258                 if (warning_str)
3259                         play_warning = atol(warning_str);
3260                 if (warnfreq_str)
3261                         warning_freq = atol(warnfreq_str);
3262
3263                 if (!timelimit) {
3264                         timelimit = play_warning = warning_freq = 0;
3265                         warning_sound = NULL;
3266                 } else if (play_warning > timelimit) {
3267                         if (!warning_freq) {
3268                                 play_warning = 0;
3269                         } else {
3270                                 while (play_warning > timelimit)
3271                                         play_warning -= warning_freq;
3272                                 if (play_warning < 1)
3273                                         play_warning = warning_freq = 0;
3274                         }
3275                 }
3276
3277                 ast_verb(3, "Setting conference duration limit to: %ldms.\n", timelimit);
3278                 if (play_warning) {
3279                         ast_verb(3, "Setting warning time to %ldms from the conference duration limit.\n", play_warning);
3280                 }
3281                 if (warning_freq) {
3282                         ast_verb(3, "Setting warning frequency to %ldms.\n", warning_freq);
3283                 }
3284
3285                 ast_channel_lock(chan);
3286                 if ((var = pbx_builtin_getvar_helper(chan, "CONF_LIMIT_WARNING_FILE"))) {
3287                         var = ast_strdupa(var);
3288                 }
3289                 ast_channel_unlock(chan);
3290
3291                 warning_sound = var ? var : "timeleft";
3292
3293                 ast_channel_lock(chan);
3294                 if ((var = pbx_builtin_getvar_helper(chan, "CONF_LIMIT_TIMEOUT_FILE"))) {
3295                         var = ast_strdupa(var);
3296                 }
3297                 ast_channel_unlock(chan);
3298
3299                 end_sound = var ? var : NULL;
3300
3301                 /* undo effect of S(x) in case they are both used */
3302                 calldurationlimit = 0;
3303                 /* more efficient do it like S(x) does since no advanced opts */
3304                 if (!play_warning && !end_sound && timelimit) {
3305                         calldurationlimit = timelimit / 1000;
3306                         timelimit = play_warning = warning_freq = 0;
3307                 } else {
3308                         ast_debug(2, "Limit Data for this call:\n");
3309                         ast_debug(2, "- timelimit     = %ld\n", timelimit);
3310                         ast_debug(2, "- play_warning  = %ld\n", play_warning);
3311                         ast_debug(2, "- warning_freq  = %ld\n", warning_freq);
3312                         ast_debug(2, "- warning_sound = %s\n", warning_sound ? warning_sound : "UNDEF");
3313                         ast_debug(2, "- end_sound     = %s\n", end_sound ? end_sound : "UNDEF");
3314                 }
3315         }
3316
3317         /* Get exit keys */
3318         if (ast_test_flag64(confflags, CONFFLAG_KEYEXIT)) {
3319                 if (!ast_strlen_zero(optargs[OPT_ARG_EXITKEYS]))
3320                         exitkeys = ast_strdupa(optargs[OPT_ARG_EXITKEYS]);
3321                 else
3322                         exitkeys = ast_strdupa("#"); /* Default */
3323         }
3324         
3325         if (ast_test_flag64(confflags, CONFFLAG_RECORDCONF)) {
3326                 if (!conf->recordingfilename) {
3327                         const char *var;
3328                         ast_channel_lock(chan);
3329                         if ((var = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFILE"))) {
3330                                 conf->recordingfilename = ast_strdup(var);
3331                         }
3332                         if ((var = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFORMAT"))) {
3333                                 conf->recordingformat = ast_strdup(var);
3334                         }
3335                         ast_channel_unlock(chan);
3336                         if (!conf->recordingfilename) {
3337                                 snprintf(recordingtmp, sizeof(recordingtmp), "meetme-conf-rec-%s-%s", conf->confno, ast_channel_uniqueid(chan));
3338                                 conf->recordingfilename = ast_strdup(recordingtmp);
3339                         }
3340                         if (!conf->recordingformat) {
3341                                 conf->recordingformat = ast_strdup("wav");
3342                         }
3343                         ast_verb(4, "Starting recording of MeetMe Conference %s into file %s.%s.\n",
3344                                     conf->confno, conf->recordingfilename, conf->recordingformat);
3345                 }
3346         }
3347
3348         ast_mutex_lock(&conf->recordthreadlock);
3349         if ((conf->recordthread == AST_PTHREADT_NULL) && ast_test_flag64(confflags, CONFFLAG_RECORDCONF) &&
3350                 ((conf->lchan = ast_request("DAHDI", cap_slin, NULL, chan, "pseudo", NULL)))) {
3351                 ast_set_read_format(conf->lchan, ast_format_slin);
3352                 ast_set_write_format(conf->lchan, ast_format_slin);
3353                 dahdic.chan = 0;
3354                 dahdic.confno = conf->dahdiconf;
3355                 dahdic.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON;
3356                 if (ioctl(ast_channel_fd(conf->lchan, 0), DAHDI_SETCONF, &dahdic)) {
3357                         ast_log(LOG_WARNING, "Error starting listen channel\n");
3358                         ast_hangup(conf->lchan);
3359                         conf->lchan = NULL;
3360                 } else {
3361                         ast_pthread_create_detached_background(&conf->recordthread, NULL, recordthread, conf);
3362                 }
3363         }
3364         ast_mutex_unlock(&conf->recordthreadlock);
3365
3366         ast_mutex_lock(&conf->announcethreadlock);
3367         if ((conf->announcethread == AST_PTHREADT_NULL) && !ast_test_flag64(confflags, CONFFLAG_QUIET) &&
3368                 ast_test_flag64(confflags, CONFFLAG_INTROUSER | CONFFLAG_INTROUSERNOREVIEW | CONFFLAG_INTROUSER_VMREC)) {