1 /*
2 * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3 * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
4 *
5 * Version: MPL 1.1
6 *
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
11 *
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
16 *
17 * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18 *
19 * The Initial Developer of the Original Code is
20 * Anthony Minessale II <anthm@freeswitch.org>
21 * Portions created by the Initial Developer are Copyright (C)
22 * the Initial Developer. All Rights Reserved.
23 *
24 * Contributor(s):
25 *
26 * Anthony Minessale II <anthm@freeswitch.org>
27 * Neal Horman <neal at wanlink dot com>
28 * Bret McDanel <trixter at 0xdecafbad dot com>
29 * Dale Thatcher <freeswitch at dalethatcher dot com>
30 * Chris Danielson <chris at maxpowersoft dot com>
31 * Rupa Schomaker <rupa@rupa.com>
32 * David Weekly <david@weekly.org>
33 * Joao Mesquita <jmesquita@gmail.com>
34 * Raymond Chandler <intralanman@freeswitch.org>
35 * Seven Du <dujinfang@gmail.com>
36 * Emmanuel Schmidbauer <e.schmidbauer@gmail.com>
37 * William King <william.king@quentustech.com>
38 *
39 * mod_conference.c -- Software Conference Bridge
40 *
41 */
42 #include <mod_conference.h>
43
conference_utils_combine_flag_var(switch_core_session_t * session,const char * var_name)44 const char *conference_utils_combine_flag_var(switch_core_session_t *session, const char *var_name)
45 {
46 switch_event_header_t *hp;
47 switch_event_t *event, *cevent;
48 char *ret = NULL;
49 switch_channel_t *channel = switch_core_session_get_channel(session);
50
51 switch_core_get_variables(&event);
52 switch_channel_get_variables(channel, &cevent);
53 switch_event_merge(event, cevent);
54
55
56 for (hp = event->headers; hp; hp = hp->next) {
57 char *var = hp->name;
58 char *val = hp->value;
59
60 if (!strcasecmp(var, var_name)) {
61 if (hp->idx) {
62 int i;
63 for (i = 0; i < hp->idx; i++) {
64 if (zstr(ret)) {
65 ret = switch_core_session_sprintf(session, "%s", hp->array[i]);
66 } else {
67 ret = switch_core_session_sprintf(session, "%s|%s", ret, hp->array[i]);
68 }
69 }
70 } else {
71 if (zstr(ret)) {
72 ret = switch_core_session_sprintf(session, "%s", val);
73 } else {
74 ret = switch_core_session_sprintf(session, "%s|%s", ret, val);
75 }
76 }
77 } else if (!strncasecmp(var, var_name, strlen(var_name)) && switch_true(val)) {
78 char *p = var + strlen(var_name);
79
80 if (*p == '_' && *(p+1)) {
81 p++;
82 ret = switch_core_session_sprintf(session, "%s|%s", ret, p);
83 }
84 }
85 }
86
87
88 switch_event_destroy(&event);
89 switch_event_destroy(&cevent);
90
91 return ret;
92
93 }
94
conference_utils_set_mflags(const char * flags,member_flag_t * f)95 void conference_utils_set_mflags(const char *flags, member_flag_t *f)
96 {
97 if (flags) {
98 char *dup = strdup(flags);
99 char *p;
100 char *argv[10] = { 0 };
101 int i, argc = 0;
102
103 f[MFLAG_CAN_SPEAK] = f[MFLAG_CAN_HEAR] = f[MFLAG_CAN_BE_SEEN] = 1;
104
105 for (p = dup; p && *p; p++) {
106 if (*p == ',') {
107 *p = '|';
108 }
109 }
110
111 argc = switch_separate_string(dup, '|', argv, (sizeof(argv) / sizeof(argv[0])));
112
113 for (i = 0; i < argc && argv[i]; i++) {
114 if (!strcasecmp(argv[i], "mute")) {
115 f[MFLAG_CAN_SPEAK] = 0;
116 f[MFLAG_TALKING] = 0;
117 } else if (!strcasecmp(argv[i], "vmute")) {
118 f[MFLAG_CAN_BE_SEEN] = 0;
119 } else if (!strcasecmp(argv[i], "deaf")) {
120 f[MFLAG_CAN_HEAR] = 0;
121 } else if (!strcasecmp(argv[i], "blind")) {
122 f[MFLAG_CAN_SEE] = 0;
123 } else if (!strcasecmp(argv[i], "mute-detect")) {
124 f[MFLAG_MUTE_DETECT] = 1;
125 } else if (!strcasecmp(argv[i], "dist-dtmf")) {
126 f[MFLAG_DIST_DTMF] = 1;
127 } else if (!strcasecmp(argv[i], "moderator")) {
128 f[MFLAG_MOD] = 1;
129 } else if (!strcasecmp(argv[i], "nomoh")) {
130 f[MFLAG_NOMOH] = 1;
131 } else if (!strcasecmp(argv[i], "endconf")) {
132 f[MFLAG_ENDCONF] = 1;
133 } else if (!strcasecmp(argv[i], "mintwo")) {
134 f[MFLAG_MINTWO] = 1;
135 } else if (!strcasecmp(argv[i], "talk-data-events")) {
136 f[MFLAG_TALK_DATA_EVENTS] = 1;
137 } else if (!strcasecmp(argv[i], "video-bridge")) {
138 f[MFLAG_VIDEO_BRIDGE] = 1;
139 } else if (!strcasecmp(argv[i], "ghost")) {
140 f[MFLAG_GHOST] = 1;
141 } else if (!strcasecmp(argv[i], "join-only")) {
142 f[MFLAG_JOIN_ONLY] = 1;
143 } else if (!strcasecmp(argv[i], "flip-video")) {
144 f[MFLAG_FLIP_VIDEO] = 1;
145 } else if (!strcasecmp(argv[i], "positional")) {
146 f[MFLAG_POSITIONAL] = 1;
147 } else if (!strcasecmp(argv[i], "no-positional")) {
148 f[MFLAG_NO_POSITIONAL] = 1;
149 } else if (!strcasecmp(argv[i], "join-vid-floor")) {
150 f[MFLAG_JOIN_VID_FLOOR] = 1;
151 } else if (!strcasecmp(argv[i], "no-video-blanks")) {
152 f[MFLAG_NO_VIDEO_BLANKS] = 1;
153 } else if (!strcasecmp(argv[i], "no-minimize-encoding")) {
154 f[MFLAG_NO_MINIMIZE_ENCODING] = 1;
155 } else if (!strcasecmp(argv[i], "second-screen")) {
156 f[MFLAG_SECOND_SCREEN] = 1;
157 f[MFLAG_CAN_SPEAK] = 0;
158 f[MFLAG_TALKING] = 0;
159 f[MFLAG_CAN_HEAR] = 0;
160 f[MFLAG_SILENT] = 1;
161 }
162 }
163
164 free(dup);
165 }
166 }
167
168
169
conference_utils_set_cflags(const char * flags,conference_flag_t * f)170 void conference_utils_set_cflags(const char *flags, conference_flag_t *f)
171 {
172 if (flags) {
173 char *dup = strdup(flags);
174 char *p;
175 char *argv[25] = { 0 };
176 int i, argc = 0;
177
178 for (p = dup; p && *p; p++) {
179 if (*p == ',') {
180 *p = '|';
181 }
182 }
183
184 argc = switch_separate_string(dup, '|', argv, (sizeof(argv) / sizeof(argv[0])));
185
186 for (i = 0; i < argc && argv[i]; i++) {
187 if (!strcasecmp(argv[i], "wait-mod")) {
188 f[CFLAG_WAIT_MOD] = 1;
189 } else if (!strcasecmp(argv[i], "video-floor-only")) {
190 f[CFLAG_VID_FLOOR] = 1;
191 } else if (!strcasecmp(argv[i], "audio-always")) {
192 f[CFLAG_AUDIO_ALWAYS] = 1;
193 } else if (!strcasecmp(argv[i], "restart-auto-record")) {
194 f[CFLAG_CONF_RESTART_AUTO_RECORD] = 1;
195 } else if (!strcasecmp(argv[i], "json-events")) {
196 f[CFLAG_JSON_EVENTS] = 1;
197 } else if (!strcasecmp(argv[i], "livearray-sync")) {
198 f[CFLAG_LIVEARRAY_SYNC] = 1;
199 } else if (!strcasecmp(argv[i], "livearray-json-status")) {
200 f[CFLAG_JSON_STATUS] = 1;
201 } else if (!strcasecmp(argv[i], "rfc-4579")) {
202 f[CFLAG_RFC4579] = 1;
203 } else if (!strcasecmp(argv[i], "auto-3d-position")) {
204 f[CFLAG_POSITIONAL] = 1;
205 } else if (!strcasecmp(argv[i], "minimize-video-encoding")) {
206 f[CFLAG_MINIMIZE_VIDEO_ENCODING] = 1;
207 } else if (!strcasecmp(argv[i], "video-bridge-first-two")) {
208 f[CFLAG_VIDEO_BRIDGE_FIRST_TWO] = 1;
209 } else if (!strcasecmp(argv[i], "video-required-for-canvas")) {
210 f[CFLAG_VIDEO_REQUIRED_FOR_CANVAS] = 1;
211 } else if (!strcasecmp(argv[i], "video-mute-exit-canvas")) {
212 f[CFLAG_VIDEO_MUTE_EXIT_CANVAS] = 1;
213 } else if (!strcasecmp(argv[i], "manage-inbound-video-bitrate")) {
214 f[CFLAG_MANAGE_INBOUND_VIDEO_BITRATE] = 1;
215 } else if (!strcasecmp(argv[i], "video-muxing-personal-canvas")) {
216 f[CFLAG_PERSONAL_CANVAS] = 1;
217 } else if (!strcasecmp(argv[i], "ded-vid-layer-audio-floor")) {
218 f[CFLAG_DED_VID_LAYER_AUDIO_FLOOR] = 1;
219 }
220 }
221
222 free(dup);
223 }
224 }
225
226
conference_utils_clear_eflags(char * events,uint32_t * f)227 void conference_utils_clear_eflags(char *events, uint32_t *f)
228 {
229 char buf[512] = "";
230 char *next = NULL;
231 char *event = buf;
232
233 if (events) {
234 switch_copy_string(buf, events, sizeof(buf));
235
236 while (event) {
237 next = strchr(event, ',');
238 if (next) {
239 *next++ = '\0';
240 }
241
242 if (!strcmp(event, "del-member")) {
243 *f &= ~EFLAG_DEL_MEMBER;
244 } else if (!strcmp(event, "energy-level")) {
245 *f &= ~EFLAG_ENERGY_LEVEL;
246 } else if (!strcmp(event, "volume-level")) {
247 *f &= ~EFLAG_VOLUME_LEVEL;
248 } else if (!strcmp(event, "gain-level")) {
249 *f &= ~EFLAG_GAIN_LEVEL;
250 } else if (!strcmp(event, "dtmf")) {
251 *f &= ~EFLAG_DTMF;
252 } else if (!strcmp(event, "stop-talking")) {
253 *f &= ~EFLAG_STOP_TALKING;
254 } else if (!strcmp(event, "start-talking")) {
255 *f &= ~EFLAG_START_TALKING;
256 } else if (!strcmp(event, "mute-detect")) {
257 *f &= ~EFLAG_MUTE_DETECT;
258 } else if (!strcmp(event, "mute-member")) {
259 *f &= ~EFLAG_MUTE_MEMBER;
260 } else if (!strcmp(event, "hold-member")) {
261 *f &= ~EFLAG_HOLD_MEMBER;
262 } else if (!strcmp(event, "kick-member")) {
263 *f &= ~EFLAG_KICK_MEMBER;
264 } else if (!strcmp(event, "dtmf-member")) {
265 *f &= ~EFLAG_DTMF_MEMBER;
266 } else if (!strcmp(event, "energy-level-member")) {
267 *f &= ~EFLAG_ENERGY_LEVEL_MEMBER;
268 } else if (!strcmp(event, "volume-in-member")) {
269 *f &= ~EFLAG_VOLUME_IN_MEMBER;
270 } else if (!strcmp(event, "volume-out-member")) {
271 *f &= ~EFLAG_VOLUME_OUT_MEMBER;
272 } else if (!strcmp(event, "play-file")) {
273 *f &= ~EFLAG_PLAY_FILE;
274 } else if (!strcmp(event, "play-file-done")) {
275 *f &= ~EFLAG_PLAY_FILE_DONE;
276 } else if (!strcmp(event, "play-file-member")) {
277 *f &= ~EFLAG_PLAY_FILE_MEMBER;
278 } else if (!strcmp(event, "speak-text")) {
279 *f &= ~EFLAG_SPEAK_TEXT;
280 } else if (!strcmp(event, "speak-text-member")) {
281 *f &= ~EFLAG_SPEAK_TEXT_MEMBER;
282 } else if (!strcmp(event, "lock")) {
283 *f &= ~EFLAG_LOCK;
284 } else if (!strcmp(event, "unlock")) {
285 *f &= ~EFLAG_UNLOCK;
286 } else if (!strcmp(event, "transfer")) {
287 *f &= ~EFLAG_TRANSFER;
288 } else if (!strcmp(event, "bgdial-result")) {
289 *f &= ~EFLAG_BGDIAL_RESULT;
290 } else if (!strcmp(event, "floor-change")) {
291 *f &= ~EFLAG_FLOOR_CHANGE;
292 } else if (!strcmp(event, "record")) {
293 *f &= ~EFLAG_RECORD;
294 }
295
296 event = next;
297 }
298 }
299 }
300
301
conference_utils_merge_mflags(member_flag_t * a,member_flag_t * b)302 void conference_utils_merge_mflags(member_flag_t *a, member_flag_t *b)
303 {
304 int x;
305
306 for (x = 0; x < MFLAG_MAX; x++) {
307 if (b[x]) a[x] = 1;
308 }
309 }
310
conference_utils_set_flag(conference_obj_t * conference,conference_flag_t flag)311 void conference_utils_set_flag(conference_obj_t *conference, conference_flag_t flag)
312 {
313 conference->flags[flag] = 1;
314 }
conference_utils_set_flag_locked(conference_obj_t * conference,conference_flag_t flag)315 void conference_utils_set_flag_locked(conference_obj_t *conference, conference_flag_t flag)
316 {
317 switch_mutex_lock(conference->flag_mutex);
318 conference->flags[flag] = 1;
319 switch_mutex_unlock(conference->flag_mutex);
320 }
conference_utils_clear_flag(conference_obj_t * conference,conference_flag_t flag)321 void conference_utils_clear_flag(conference_obj_t *conference, conference_flag_t flag)
322 {
323 conference->flags[flag] = 0;
324 }
conference_utils_clear_flag_locked(conference_obj_t * conference,conference_flag_t flag)325 void conference_utils_clear_flag_locked(conference_obj_t *conference, conference_flag_t flag)
326 {
327 switch_mutex_lock(conference->flag_mutex);
328 conference->flags[flag] = 0;
329 switch_mutex_unlock(conference->flag_mutex);
330 }
conference_utils_test_flag(conference_obj_t * conference,conference_flag_t flag)331 switch_bool_t conference_utils_test_flag(conference_obj_t *conference, conference_flag_t flag)
332 {
333 return !!conference->flags[flag];
334 }
335
336 #if 0
337 void conference_utils_conference_utils_set_mflag(conference_obj_t *conference, member_flag_t mflag)
338 {
339 conference->mflags[mflag] = 1;
340 }
341
342 void conference_utils_clear_mflag(conference_obj_t *conference, member_flag_t mflag)
343 {
344 conference->mflags[mflag] = 0;
345 }
346
347 switch_bool_t conference_utils_test_mflag(conference_obj_t *conference, member_flag_t mflag)
348 {
349 return !!conference->mflags[mflag];
350 }
351 #endif
352
conference_utils_member_set_flag(conference_member_t * member,member_flag_t flag)353 void conference_utils_member_set_flag(conference_member_t *member, member_flag_t flag)
354 {
355 member->flags[flag] = 1;
356
357 if (flag == MFLAG_SECOND_SCREEN) {
358 member->flags[MFLAG_CAN_SPEAK] = 0;
359 member->flags[MFLAG_CAN_HEAR] = 0;
360 member->flags[MFLAG_CAN_BE_SEEN] = 0;
361 }
362 }
363
conference_utils_member_set_flag_locked(conference_member_t * member,member_flag_t flag)364 void conference_utils_member_set_flag_locked(conference_member_t *member, member_flag_t flag)
365 {
366 switch_mutex_lock(member->flag_mutex);
367 conference_utils_member_set_flag(member, flag);
368 switch_mutex_unlock(member->flag_mutex);
369 }
370
check_cleared_flag(conference_member_t * member,member_flag_t flag)371 static void check_cleared_flag(conference_member_t *member, member_flag_t flag)
372 {
373 if (flag == MFLAG_RUNNING && member->session) {
374 switch_core_session_kill_channel(member->session, SWITCH_SIG_BREAK);
375 }
376 }
377
conference_utils_member_clear_flag(conference_member_t * member,member_flag_t flag)378 void conference_utils_member_clear_flag(conference_member_t *member, member_flag_t flag)
379 {
380 member->flags[flag] = 0;
381 check_cleared_flag(member, flag);
382 }
conference_utils_member_clear_flag_locked(conference_member_t * member,member_flag_t flag)383 void conference_utils_member_clear_flag_locked(conference_member_t *member, member_flag_t flag)
384 {
385 switch_mutex_lock(member->flag_mutex);
386 member->flags[flag] = 0;
387 switch_mutex_unlock(member->flag_mutex);
388 check_cleared_flag(member, flag);
389 }
conference_utils_member_test_flag(conference_member_t * member,member_flag_t flag)390 switch_bool_t conference_utils_member_test_flag(conference_member_t *member, member_flag_t flag)
391 {
392 return !!member->flags[flag];
393 }
394
395 /* For Emacs:
396 * Local Variables:
397 * mode:c
398 * indent-tabs-mode:t
399 * tab-width:4
400 * c-basic-offset:4
401 * End:
402 * For VIM:
403 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
404 */
405