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