conf_state_multi_marked.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2012, Terry Wilson
  5. *
  6. * Terry Wilson <twilson@digium.com>
  7. *
  8. * See http://www.asterisk.org for more information about
  9. * the Asterisk project. Please do not directly contact
  10. * any of the maintainers of this project for assistance;
  11. * the project provides a web site, mailing lists and IRC
  12. * channels for your use.
  13. *
  14. * This program is free software, distributed under the terms of
  15. * the GNU General Public License Version 2. See the LICENSE file
  16. * at the top of the source tree.
  17. *
  18. * Please follow coding guidelines
  19. * http://svn.digium.com/view/asterisk/trunk/doc/CODING-GUIDELINES
  20. */
  21. /*! \file
  22. *
  23. * \brief Confbridge state handling for the MULTI_MARKED state
  24. *
  25. * \author\verbatim Terry Wilson <twilson@digium.com> \endverbatim
  26. *
  27. * \ingroup applications
  28. */
  29. /*** MODULEINFO
  30. <support_level>core</support_level>
  31. ***/
  32. #include "asterisk.h"
  33. #include "asterisk/utils.h"
  34. #include "asterisk/linkedlists.h"
  35. #include "include/confbridge.h"
  36. #include "asterisk/musiconhold.h"
  37. #include "include/conf_state.h"
  38. #include "asterisk/pbx.h"
  39. static void join_active(struct confbridge_user *user);
  40. static void join_marked(struct confbridge_user *user);
  41. static void leave_active(struct confbridge_user *user);
  42. static void leave_marked(struct confbridge_user *user);
  43. static void transition_to_marked(struct confbridge_user *user);
  44. static struct confbridge_state STATE_MULTI_MARKED = {
  45. .name = "MULTI_MARKED",
  46. .join_unmarked = join_active,
  47. .join_waitmarked = join_active,
  48. .join_marked = join_marked,
  49. .leave_unmarked = leave_active,
  50. .leave_waitmarked = leave_active,
  51. .leave_marked = leave_marked,
  52. .entry = transition_to_marked,
  53. };
  54. struct confbridge_state *CONF_STATE_MULTI_MARKED = &STATE_MULTI_MARKED;
  55. static void join_active(struct confbridge_user *user)
  56. {
  57. conf_add_user_active(user->conference, user);
  58. conf_update_user_mute(user);
  59. }
  60. static void join_marked(struct confbridge_user *user)
  61. {
  62. conf_add_user_marked(user->conference, user);
  63. conf_update_user_mute(user);
  64. }
  65. static void leave_active(struct confbridge_user *user)
  66. {
  67. conf_remove_user_active(user->conference, user);
  68. if (user->conference->activeusers == 1) {
  69. conf_change_state(user, CONF_STATE_SINGLE_MARKED);
  70. }
  71. }
  72. static void leave_marked(struct confbridge_user *user)
  73. {
  74. struct confbridge_user *user_iter;
  75. int need_prompt = 0;
  76. conf_remove_user_marked(user->conference, user);
  77. if (user->conference->markedusers == 0) {
  78. AST_LIST_TRAVERSE_SAFE_BEGIN(&user->conference->active_list, user_iter, list) {
  79. /* Kick ENDMARKED cbu_iters */
  80. if (ast_test_flag(&user_iter->u_profile, USER_OPT_ENDMARKED) && !user_iter->kicked) {
  81. if (ast_test_flag(&user_iter->u_profile, USER_OPT_WAITMARKED)
  82. && !ast_test_flag(&user_iter->u_profile, USER_OPT_MARKEDUSER)) {
  83. AST_LIST_REMOVE_CURRENT(list);
  84. user_iter->conference->activeusers--;
  85. AST_LIST_INSERT_TAIL(&user_iter->conference->waiting_list, user_iter, list);
  86. user_iter->conference->waitingusers++;
  87. }
  88. user_iter->kicked = 1;
  89. pbx_builtin_setvar_helper(user_iter->chan, "CONFBRIDGE_RESULT", "ENDMARKED");
  90. ast_bridge_remove(user_iter->conference->bridge, user_iter->chan);
  91. } else if (ast_test_flag(&user_iter->u_profile, USER_OPT_WAITMARKED)
  92. && !ast_test_flag(&user_iter->u_profile, USER_OPT_MARKEDUSER)) {
  93. need_prompt = 1;
  94. AST_LIST_REMOVE_CURRENT(list);
  95. user_iter->conference->activeusers--;
  96. AST_LIST_INSERT_TAIL(&user_iter->conference->waiting_list, user_iter, list);
  97. user_iter->conference->waitingusers++;
  98. } else {
  99. /* User is neither wait_marked nor end_marked; however, they
  100. * should still hear the prompt.
  101. */
  102. need_prompt = 1;
  103. }
  104. }
  105. AST_LIST_TRAVERSE_SAFE_END;
  106. }
  107. switch (user->conference->activeusers) {
  108. case 0:
  109. /* Implies markedusers == 0 */
  110. switch (user->conference->waitingusers) {
  111. case 0:
  112. conf_change_state(user, CONF_STATE_EMPTY);
  113. break;
  114. default:
  115. conf_change_state(user, CONF_STATE_INACTIVE);
  116. break;
  117. }
  118. break;
  119. case 1:
  120. switch (user->conference->markedusers) {
  121. case 0:
  122. conf_change_state(user, CONF_STATE_SINGLE);
  123. break;
  124. case 1:
  125. /* XXX I seem to remember doing this for a reason, but right now it escapes me
  126. * how we could possibly ever have a waiting user while we have a marked user */
  127. switch (user->conference->waitingusers) {
  128. case 0:
  129. conf_change_state(user, CONF_STATE_SINGLE_MARKED);
  130. break;
  131. case 1:
  132. break; /* Stay in marked */
  133. }
  134. break;
  135. }
  136. break;
  137. default:
  138. switch (user->conference->markedusers) {
  139. case 0:
  140. conf_change_state(user, CONF_STATE_MULTI);
  141. break;
  142. default:
  143. break; /* Stay in marked */
  144. }
  145. }
  146. if (need_prompt) {
  147. /* Play back the audio prompt saying the leader has left the conference */
  148. if (!ast_test_flag(&user->u_profile, USER_OPT_QUIET)) {
  149. async_play_sound_file(user->conference,
  150. conf_get_sound(CONF_SOUND_LEADER_HAS_LEFT, user->conference->b_profile.sounds),
  151. NULL);
  152. }
  153. AST_LIST_TRAVERSE(&user->conference->waiting_list, user_iter, list) {
  154. if (user_iter->kicked) {
  155. continue;
  156. }
  157. if (ast_test_flag(&user_iter->u_profile, USER_OPT_MUSICONHOLD)) {
  158. conf_moh_start(user_iter);
  159. }
  160. conf_update_user_mute(user_iter);
  161. }
  162. }
  163. }
  164. static int post_join_play_begin(struct confbridge_user *user)
  165. {
  166. int res;
  167. ast_autoservice_start(user->chan);
  168. res = play_sound_file(user->conference,
  169. conf_get_sound(CONF_SOUND_BEGIN, user->conference->b_profile.sounds));
  170. ast_autoservice_stop(user->chan);
  171. return res;
  172. }
  173. static void transition_to_marked(struct confbridge_user *user)
  174. {
  175. struct confbridge_user *user_iter;
  176. int waitmarked_moved = 0;
  177. /* Move all waiting users to active, stopping MOH and unmuting if necessary */
  178. AST_LIST_TRAVERSE_SAFE_BEGIN(&user->conference->waiting_list, user_iter, list) {
  179. AST_LIST_REMOVE_CURRENT(list);
  180. user->conference->waitingusers--;
  181. AST_LIST_INSERT_TAIL(&user->conference->active_list, user_iter, list);
  182. user->conference->activeusers++;
  183. if (user_iter->playing_moh) {
  184. conf_moh_stop(user_iter);
  185. }
  186. conf_update_user_mute(user_iter);
  187. waitmarked_moved++;
  188. }
  189. AST_LIST_TRAVERSE_SAFE_END;
  190. /* Play the audio file stating that the conference is beginning */
  191. if (user->conference->markedusers == 1
  192. && ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER)
  193. && !ast_test_flag(&user->u_profile, USER_OPT_QUIET)
  194. && waitmarked_moved) {
  195. conf_add_post_join_action(user, post_join_play_begin);
  196. }
  197. }