app_confbridge: Fix memory leak on reload.
[asterisk/asterisk.git] / apps / confbridge / include / confbridge.h
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2011, Digium, Inc.
5  *
6  * David Vossel <dvossel@digium.com>
7  * Joshua Colp <jcolp@digium.com>
8  *
9  * See http://www.asterisk.org for more information about
10  * the Asterisk project. Please do not directly contact
11  * any of the maintainers of this project for assistance;
12  * the project provides a web site, mailing lists and IRC
13  * channels for your use.
14  *
15  * This program is free software, distributed under the terms of
16  * the GNU General Public License Version 2. See the LICENSE file
17  * at the top of the source tree.
18  */
19
20
21 #ifndef _CONFBRIDGE_H
22 #define _CONFBRIDGE_H
23
24 #include "asterisk.h"
25 #include "asterisk/app.h"
26 #include "asterisk/logger.h"
27 #include "asterisk/linkedlists.h"
28 #include "asterisk/channel.h"
29 #include "asterisk/bridging.h"
30 #include "asterisk/bridging_features.h"
31 #include "conf_state.h"
32
33 /* Maximum length of a conference bridge name */
34 #define MAX_CONF_NAME 32
35 /* Maximum length of a conference pin */
36 #define MAX_PIN     80
37
38 #define DEFAULT_USER_PROFILE "default_user"
39 #define DEFAULT_BRIDGE_PROFILE "default_bridge"
40
41 #define DEFAULT_TALKING_THRESHOLD 160
42 #define DEFAULT_SILENCE_THRESHOLD 2500
43
44 enum user_profile_flags {
45         USER_OPT_ADMIN =        (1 << 0), /*!< Set if the caller is an administrator */
46         USER_OPT_NOONLYPERSON = (1 << 1), /*!< Set if the "you are currently the only person in this conference" sound file should not be played */
47         USER_OPT_MARKEDUSER =   (1 << 2), /*!< Set if the caller is a marked user */
48         USER_OPT_STARTMUTED =   (1 << 3), /*!< Set if the caller should be initially set muted */
49         USER_OPT_MUSICONHOLD =  (1 << 4), /*!< Set if music on hold should be played if nobody else is in the conference bridge */
50         USER_OPT_QUIET =        (1 << 5), /*!< Set if no audio prompts should be played */
51         USER_OPT_ANNOUNCEUSERCOUNT = (1 << 6), /*!< Set if the number of users should be announced to the caller */
52         USER_OPT_WAITMARKED =   (1 << 7), /*!< Set if the user must wait for a marked user before starting */
53         USER_OPT_ENDMARKED =    (1 << 8), /*!< Set if the user should be kicked after the last Marked user exits */
54         USER_OPT_DENOISE =      (1 << 9), /*!< Sets if denoise filter should be used on audio before mixing. */
55         USER_OPT_ANNOUNCE_JOIN_LEAVE = (1 << 10), /*!< Sets if the user's name should be recorded and announced on join and leave. */
56         USER_OPT_TALKER_DETECT = (1 << 11), /*!< Sets if start and stop talking events should generated for this user over AMI. */
57         USER_OPT_DROP_SILENCE =  (1 << 12), /*!< Sets if silence should be dropped from the mix or not. */
58         USER_OPT_DTMF_PASS    =  (1 << 13), /*!< Sets if dtmf should be passed into the conference or not */
59         USER_OPT_ANNOUNCEUSERCOUNTALL = (1 << 14), /*!< Sets if the number of users should be announced to everyone. */
60         USER_OPT_JITTERBUFFER =  (1 << 15), /*!< Places a jitterbuffer on the user. */
61 };
62
63 enum bridge_profile_flags {
64         BRIDGE_OPT_RECORD_CONFERENCE = (1 << 0), /*!< Set if the conference should be recorded */
65         BRIDGE_OPT_VIDEO_SRC_LAST_MARKED = (1 << 1), /*!< Set if conference should feed video of last marked user to all participants. */
66         BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED = (1 << 2), /*!< Set if conference should feed video of first marked user to all participants. */
67         BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER = (1 << 3), /*!< Set if conference set the video feed to follow the loudest talker.  */
68         BRIDGE_OPT_RECORD_FILE_APPEND = (1 << 4), /*!< Set if the record file should be appended to between start/stops.  */
69 };
70
71 enum conf_menu_action_id {
72         MENU_ACTION_TOGGLE_MUTE = 1,
73         MENU_ACTION_PLAYBACK,
74         MENU_ACTION_PLAYBACK_AND_CONTINUE,
75         MENU_ACTION_INCREASE_LISTENING,
76         MENU_ACTION_DECREASE_LISTENING,
77         MENU_ACTION_RESET_LISTENING,
78         MENU_ACTION_RESET_TALKING,
79         MENU_ACTION_INCREASE_TALKING,
80         MENU_ACTION_DECREASE_TALKING,
81         MENU_ACTION_DIALPLAN_EXEC,
82         MENU_ACTION_ADMIN_TOGGLE_LOCK,
83         MENU_ACTION_ADMIN_KICK_LAST,
84         MENU_ACTION_LEAVE,
85         MENU_ACTION_NOOP,
86         MENU_ACTION_SET_SINGLE_VIDEO_SRC,
87         MENU_ACTION_RELEASE_SINGLE_VIDEO_SRC,
88         MENU_ACTION_PARTICIPANT_COUNT,
89         MENU_ACTION_ADMIN_TOGGLE_MUTE_PARTICIPANTS,
90 };
91
92 /*! The conference menu action contains both
93  *  the action id that represents the action that
94  *  must take place, along with any data associated
95  *  with that action. */
96 struct conf_menu_action {
97         enum conf_menu_action_id id;
98         union {
99                 char playback_file[PATH_MAX];
100                 struct {
101                         char context[AST_MAX_CONTEXT];
102                         char exten[AST_MAX_EXTENSION];
103                         int priority;
104                 } dialplan_args;
105         } data;
106         AST_LIST_ENTRY(conf_menu_action) action;
107 };
108
109 /*! Conference menu entries contain the DTMF sequence
110  *  and the list of actions that are associated with that
111  *  sequence. */
112 struct conf_menu_entry {
113         /*! the DTMF sequence that triggers the actions */
114         char dtmf[MAXIMUM_DTMF_FEATURE_STRING];
115         /*! The actions associated with this menu entry. */
116         AST_LIST_HEAD_NOLOCK(, conf_menu_action) actions;
117         AST_LIST_ENTRY(conf_menu_entry) entry;
118 };
119
120 /*! Conference menu structure.  Contains a list
121  * of DTMF sequences coupled with the actions those
122  * sequences invoke.*/
123 struct conf_menu {
124         char name[128];
125         AST_LIST_HEAD_NOLOCK(, conf_menu_entry) entries;
126 };
127
128 struct user_profile {
129         char name[128];
130         char pin[MAX_PIN];
131         char moh_class[128];
132         char announcement[PATH_MAX];
133         unsigned int flags;
134         unsigned int announce_user_count_all_after;
135         /*! The time in ms of talking before a user is considered to be talking by the dsp. */
136         unsigned int talking_threshold;
137         /*! The time in ms of silence before a user is considered to be silent by the dsp. */
138         unsigned int silence_threshold;
139 };
140
141 enum conf_sounds {
142         CONF_SOUND_HAS_JOINED,
143         CONF_SOUND_HAS_LEFT,
144         CONF_SOUND_KICKED,
145         CONF_SOUND_MUTED,
146         CONF_SOUND_UNMUTED,
147         CONF_SOUND_ONLY_ONE,
148         CONF_SOUND_THERE_ARE,
149         CONF_SOUND_OTHER_IN_PARTY,
150         CONF_SOUND_PLACE_IN_CONF,
151         CONF_SOUND_WAIT_FOR_LEADER,
152         CONF_SOUND_LEADER_HAS_LEFT,
153         CONF_SOUND_GET_PIN,
154         CONF_SOUND_INVALID_PIN,
155         CONF_SOUND_ONLY_PERSON,
156         CONF_SOUND_LOCKED,
157         CONF_SOUND_LOCKED_NOW,
158         CONF_SOUND_UNLOCKED_NOW,
159         CONF_SOUND_ERROR_MENU,
160         CONF_SOUND_JOIN,
161         CONF_SOUND_LEAVE,
162         CONF_SOUND_PARTICIPANTS_MUTED,
163         CONF_SOUND_PARTICIPANTS_UNMUTED,
164 };
165
166 struct bridge_profile_sounds {
167         AST_DECLARE_STRING_FIELDS(
168                 AST_STRING_FIELD(hasjoin);
169                 AST_STRING_FIELD(hasleft);
170                 AST_STRING_FIELD(kicked);
171                 AST_STRING_FIELD(muted);
172                 AST_STRING_FIELD(unmuted);
173                 AST_STRING_FIELD(onlyone);
174                 AST_STRING_FIELD(thereare);
175                 AST_STRING_FIELD(otherinparty);
176                 AST_STRING_FIELD(placeintoconf);
177                 AST_STRING_FIELD(waitforleader);
178                 AST_STRING_FIELD(leaderhasleft);
179                 AST_STRING_FIELD(getpin);
180                 AST_STRING_FIELD(invalidpin);
181                 AST_STRING_FIELD(onlyperson);
182                 AST_STRING_FIELD(locked);
183                 AST_STRING_FIELD(lockednow);
184                 AST_STRING_FIELD(unlockednow);
185                 AST_STRING_FIELD(errormenu);
186                 AST_STRING_FIELD(leave);
187                 AST_STRING_FIELD(join);
188                 AST_STRING_FIELD(participantsmuted);
189                 AST_STRING_FIELD(participantsunmuted);
190         );
191 };
192
193 struct bridge_profile {
194         char name[64];
195         char rec_file[PATH_MAX];
196         unsigned int flags;
197         unsigned int max_members;          /*!< The maximum number of participants allowed in the conference */
198         unsigned int internal_sample_rate; /*!< The internal sample rate of the bridge. 0 when set to auto adjust mode. */
199         unsigned int mix_interval;  /*!< The internal mixing interval used by the bridge. When set to 0 the bridgewill use a default interval. */
200         struct bridge_profile_sounds *sounds;
201 };
202
203 /*! \brief The structure that represents a conference bridge */
204 struct confbridge_conference {
205         char name[MAX_CONF_NAME];                                         /*!< Name of the conference bridge */
206         struct confbridge_state *state;                                   /*!< Conference state information */
207         struct ast_bridge *bridge;                                        /*!< Bridge structure doing the mixing */
208         struct bridge_profile b_profile;                                  /*!< The Bridge Configuration Profile */
209         unsigned int activeusers;                                         /*!< Number of active users present */
210         unsigned int markedusers;                                         /*!< Number of marked users present */
211         unsigned int waitingusers;                                        /*!< Number of waiting users present */
212         unsigned int locked:1;                                            /*!< Is this conference bridge locked? */
213         unsigned int muted:1;                                             /*!< Is this conference bridge muted? */
214         unsigned int record_state:2;                                      /*!< Whether recording is started, stopped, or should exit */
215         struct ast_channel *playback_chan;                                /*!< Channel used for playback into the conference bridge */
216         struct ast_channel *record_chan;                                  /*!< Channel used for recording the conference */
217         pthread_t record_thread;                                          /*!< The thread the recording chan lives in */
218         ast_mutex_t playback_lock;                                        /*!< Lock used for playback channel */
219         ast_mutex_t record_lock;                                          /*!< Lock used for the record thread */
220         ast_cond_t record_cond;                                           /*!< Recording condition variable */
221         AST_LIST_HEAD_NOLOCK(, confbridge_user) active_list;              /*!< List of users participating in the conference bridge */
222         AST_LIST_HEAD_NOLOCK(, confbridge_user) waiting_list;             /*!< List of users waiting to join the conference bridge */
223 };
224
225 extern struct ao2_container *conference_bridges;
226
227 struct post_join_action {
228         int (*func)(struct confbridge_user *user);
229         AST_LIST_ENTRY(post_join_action) list;
230 };
231
232 /*! \brief The structure that represents a conference bridge user */
233 struct confbridge_user {
234         struct confbridge_conference *conference;    /*!< Conference bridge they are participating in */
235         struct bridge_profile b_profile;             /*!< The Bridge Configuration Profile */
236         struct user_profile u_profile;               /*!< The User Configuration Profile */
237         char menu_name[64];                          /*!< The name of the DTMF menu assigned to this user */
238         char name_rec_location[PATH_MAX];            /*!< Location of the User's name recorded file if it exists */
239         struct ast_channel *chan;                    /*!< Asterisk channel participating */
240         struct ast_bridge_features features;         /*!< Bridge features structure */
241         struct ast_bridge_tech_optimizations tech_args; /*!< Bridge technology optimizations for talk detection */
242         unsigned int suspended_moh;                  /*!< Count of active suspended MOH actions. */
243         unsigned int kicked:1;                       /*!< User has been kicked from the conference */
244         unsigned int playing_moh:1;                  /*!< MOH is currently being played to the user */
245         AST_LIST_HEAD_NOLOCK(, post_join_action) post_join_list; /*!< List of sounds to play after joining */;
246         AST_LIST_ENTRY(confbridge_user) list;        /*!< Linked list information */
247 };
248
249 /*! \brief load confbridge.conf file */
250 int conf_load_config(void);
251
252 /*! \brief reload confbridge.conf file */
253 int conf_reload_config(void);
254
255 /*! \brief destroy the information loaded from the confbridge.conf file*/
256 void conf_destroy_config(void);
257
258 /*!
259  * \brief find a user profile given a user profile's name and store
260  * that profile in result structure.
261  *
262  * \details This function first attempts to find any custom user
263  * profile that might exist on a channel datastore, if that doesn't
264  * exist it looks up the provided user profile name, if that doesn't
265  * exist either the default_user profile is used.
266
267  * \retval user profile on success
268  * \retval NULL on failure
269  */
270 const struct user_profile *conf_find_user_profile(struct ast_channel *chan, const char *user_profile_name, struct user_profile *result);
271
272 /*!
273  * \brief Find a bridge profile
274  *
275  * \details Any bridge profile found using this function must be
276  * destroyed using conf_bridge_profile_destroy.  This function first
277  * attempts to find any custom bridge profile that might exist on
278  * a channel datastore, if that doesn't exist it looks up the
279  * provided bridge profile name, if that doesn't exist either
280  * the default_bridge profile is used.
281  *
282  * \retval Bridge profile on success
283  * \retval NULL on failure
284  */
285 const struct bridge_profile *conf_find_bridge_profile(struct ast_channel *chan, const char *bridge_profile_name, struct bridge_profile *result);
286
287 /*!
288  * \brief Destroy a bridge profile found by 'conf_find_bridge_profile'
289  */
290 void conf_bridge_profile_destroy(struct bridge_profile *b_profile);
291
292 /*!
293  * \brief copies a bridge profile
294  * \note conf_bridge_profile_destroy must be called on the dst structure
295  */
296 void conf_bridge_profile_copy(struct bridge_profile *dst, struct bridge_profile *src);
297
298 /*!
299  * \brief Set a DTMF menu to a conference user by menu name.
300  *
301  * \retval 0 on success, menu was found and set
302  * \retval -1 on error, menu was not found
303  */
304 int conf_set_menu_to_user(const char *menu_name, struct confbridge_user *user);
305
306 /*!
307  * \brief Finds a menu_entry in a menu structure matched by DTMF sequence.
308  *
309  * \note the menu entry found must be destroyed using conf_menu_entry_destroy()
310  *
311  * \retval 1 success, entry is found and stored in result
312  * \retval 0 failure, no entry found for given DTMF sequence
313  */
314 int conf_find_menu_entry_by_sequence(const char *dtmf_sequence, struct conf_menu *menu, struct conf_menu_entry *result);
315
316 /*!
317  * \brief Destroys and frees all the actions stored in a menu_entry structure
318  */
319 void conf_menu_entry_destroy(struct conf_menu_entry *menu_entry);
320
321 /*!
322  * \brief Once a DTMF sequence matches a sequence in the user's DTMF menu, this function will get
323  * called to perform the menu action.
324  *
325  * \param bridge_channel Bridged channel this is involving
326  * \param user the conference user to perform the action on.
327  * \param menu_entry the menu entry that invoked this callback to occur.
328  * \param menu an AO2 referenced pointer to the entire menu structure the menu_entry
329  *        derived from.
330  *
331  * \note The menu_entry is a deep copy of the entry found in the menu structure.  This allows
332  * for the menu_entry to be accessed without requiring the menu lock.  If the menu must
333  * be accessed, the menu lock must be held.  Reference counting of the menu structure is
334  * handled outside of the scope of this function.
335  *
336  * \retval 0 success
337  * \retval -1 failure
338  */
339 int conf_handle_dtmf(
340         struct ast_bridge_channel *bridge_channel,
341         struct confbridge_user *user,
342         struct conf_menu_entry *menu_entry,
343         struct conf_menu *menu);
344
345
346 /*! \brief Looks to see if sound file is stored in bridge profile sounds, if not
347  *  default sound is provided.*/
348 const char *conf_get_sound(enum conf_sounds sound, struct bridge_profile_sounds *custom_sounds);
349
350 int func_confbridge_helper(struct ast_channel *chan, const char *cmd, char *data, const char *value);
351
352 /*!
353  * \brief Play sound file into conference bridge
354  *
355  * \param conference The conference bridge to play sound file into
356  * \param filename Sound file to play
357  *
358  * \retval 0 success
359  * \retval -1 failure
360  */
361 int play_sound_file(struct confbridge_conference *conference, const char *filename);
362
363 /*! \brief Callback to be called when the conference has become empty
364  * \param conference The conference bridge
365  */
366 void conf_ended(struct confbridge_conference *conference);
367
368 /*!
369  * \brief Stop MOH for the conference user.
370  *
371  * \param user Conference user to stop MOH on.
372  *
373  * \return Nothing
374  */
375 void conf_moh_stop(struct confbridge_user *user);
376
377 /*!
378  * \brief Start MOH for the conference user.
379  *
380  * \param user Conference user to start MOH on.
381  *
382  * \return Nothing
383  */
384 void conf_moh_start(struct confbridge_user *user);
385
386 /*! \brief Attempt to mute/play MOH to the only user in the conference if they require it
387  * \param conference A conference bridge containing a single user
388  */
389 void conf_mute_only_active(struct confbridge_conference *conference);
390
391 /*! \brief Callback to execute any time we transition from zero to one marked users
392  * \param user The first marked user joining the conference
393  * \retval 0 success
394  * \retval -1 failure
395  */
396 int conf_handle_first_marked_common(struct confbridge_user *user);
397
398 /*! \brief Callback to execute any time we transition from zero to one active users
399  * \param conference The conference bridge with a single active user joined
400  * \retval 0 success
401  * \retval -1 failure
402  */
403 void conf_handle_first_join(struct confbridge_conference *conference);
404
405 /*! \brief Handle actions every time a waitmarked user joins w/o a marked user present
406  * \param user The waitmarked user
407  * \retval 0 success
408  * \retval -1 failure
409  */
410 int conf_handle_inactive_waitmarked(struct confbridge_user *user);
411
412 /*! \brief Handle actions whenever an unmarked user joins an inactive conference
413  * \note These actions seem like they could apply just as well to a marked user
414  * and possibly be made to happen any time transitioning to a single state.
415  *
416  * \param user The unmarked user
417  */
418 int conf_handle_only_unmarked(struct confbridge_user *user);
419
420 /*! \brief Handle when a conference moves to having more than one active participant
421  * \param conference The conference bridge with more than one active participant
422  */
423 void conf_handle_second_active(struct confbridge_conference *conference);
424
425 /*! \brief Add a conference bridge user as an unmarked active user of the conference
426  * \param conference The conference bridge to add the user to
427  * \param user The conference bridge user to add to the conference
428  */
429 void conf_add_user_active(struct confbridge_conference *conference, struct confbridge_user *user);
430
431 /*! \brief Add a conference bridge user as a marked active user of the conference
432  * \param conference The conference bridge to add the user to
433  * \param user The conference bridge user to add to the conference
434  */
435 void conf_add_user_marked(struct confbridge_conference *conference, struct confbridge_user *user);
436
437 /*! \brief Add a conference bridge user as an waiting user of the conference
438  * \param conference The conference bridge to add the user to
439  * \param user The conference bridge user to add to the conference
440  */
441 void conf_add_user_waiting(struct confbridge_conference *conference, struct confbridge_user *user);
442
443 /*! \brief Remove a conference bridge user from the unmarked active conference users in the conference
444  * \param conference The conference bridge to remove the user from
445  * \param user The conference bridge user to remove from the conference
446  */
447 void conf_remove_user_active(struct confbridge_conference *conference, struct confbridge_user *user);
448
449 /*! \brief Remove a conference bridge user from the marked active conference users in the conference
450  * \param conference The conference bridge to remove the user from
451  * \param user The conference bridge user to remove from the conference
452  */
453 void conf_remove_user_marked(struct confbridge_conference *conference, struct confbridge_user *user);
454
455 /*! \brief Remove a conference bridge user from the waiting conference users in the conference
456  * \param conference The conference bridge to remove the user from
457  * \param user The conference bridge user to remove from the conference
458  */
459 void conf_remove_user_waiting(struct confbridge_conference *conference, struct confbridge_user *user);
460
461 /*! \brief Queue a function to run with the given conference bridge user as an argument once the state transition is complete
462  * \param user The conference bridge user to pass to the function
463  * \param func The function to queue
464  * \retval 0 success
465  * \retval non-zero failure
466  */
467 int conf_add_post_join_action(struct confbridge_user *user, int (*func)(struct confbridge_user *user));
468
469 /*!
470  * \since 12.0
471  * \brief get the confbridge start stasis message type
472  *
473  * \retval stasis message type for confbridge start messages if it's available
474  * \retval NULL if it isn't
475  */
476 struct stasis_message_type *confbridge_start_type(void);
477
478 /*!
479  * \since 12.0
480  * \brief get the confbridge end stasis message type
481  *
482  * \retval stasis message type for confbridge end messages if it's available
483  * \retval NULL if it isn't
484  */
485 struct stasis_message_type *confbridge_end_type(void);
486
487 /*!
488  * \since 12.0
489  * \brief get the confbridge join stasis message type
490  *
491  * \retval stasis message type for confbridge join messages if it's available
492  * \retval NULL if it isn't
493  */
494 struct stasis_message_type *confbridge_join_type(void);
495
496 /*!
497  * \since 12.0
498  * \brief get the confbridge leave stasis message type
499  *
500  * \retval stasis message type for confbridge leave messages if it's available
501  * \retval NULL if it isn't
502  */
503 struct stasis_message_type *confbridge_leave_type(void);
504
505 /*!
506  * \since 12.0
507  * \brief get the confbridge start_record stasis message type
508  *
509  * \retval stasis message type for confbridge start_record messages if it's available
510  * \retval NULL if it isn't
511  */
512 struct stasis_message_type *confbridge_start_record_type(void);
513
514 /*!
515  * \since 12.0
516  * \brief get the confbridge stop_record stasis message type
517  *
518  * \retval stasis message type for confbridge stop_record messages if it's available
519  * \retval NULL if it isn't
520  */
521 struct stasis_message_type *confbridge_stop_record_type(void);
522
523 /*!
524  * \since 12.0
525  * \brief get the confbridge mute stasis message type
526  *
527  * \retval stasis message type for confbridge mute messages if it's available
528  * \retval NULL if it isn't
529  */
530 struct stasis_message_type *confbridge_mute_type(void);
531
532 /*!
533  * \since 12.0
534  * \brief get the confbridge unmute stasis message type
535  *
536  * \retval stasis message type for confbridge unmute messages if it's available
537  * \retval NULL if it isn't
538  */
539 struct stasis_message_type *confbridge_unmute_type(void);
540
541 /*!
542  * \since 12.0
543  * \brief get the confbridge talking stasis message type
544  *
545  * \retval stasis message type for confbridge talking messages if it's available
546  * \retval NULL if it isn't
547  */
548 struct stasis_message_type *confbridge_talking_type(void);
549
550 /*!
551  * \since 12.0
552  * \brief register stasis message routers to handle manager events for confbridge messages
553  *
554  * \retval 0 success
555  * \retval non-zero failure
556  */
557 int manager_confbridge_init(void);
558
559 /*!
560  * \since 12.0
561  * \brief unregister stasis message routers to handle manager events for confbridge messages
562  */
563 void manager_confbridge_shutdown(void);
564
565 /*!
566  * \brief Get ConfBridge record channel technology struct.
567  * \since 12.0.0
568  *
569  * \return ConfBridge record channel technology.
570  */
571 struct ast_channel_tech *conf_record_get_tech(void);
572
573 /*!
574  * \brief Get ConfBridge announce channel technology struct.
575  * \since 12.0.0
576  *
577  * \return ConfBridge announce channel technology.
578  */
579 struct ast_channel_tech *conf_announce_get_tech(void);
580
581 /*!
582  * \brief Remove the announcer channel from the conference.
583  * \since 12.0.0
584  *
585  * \param chan Either channel in the announcer channel pair.
586  *
587  * \return Nothing
588  */
589 void conf_announce_channel_depart(struct ast_channel *chan);
590
591 /*!
592  * \brief Push the announcer channel into the conference.
593  * \since 12.0.0
594  *
595  * \param ast Either channel in the announcer channel pair.
596  *
597  * \retval 0 on success.
598  * \retval -1 on error.
599  */
600 int conf_announce_channel_push(struct ast_channel *ast);
601 #endif