[commit] r3683 - freeswitch/branches/knhor/trunk/src/mod/applications/mod_conference
Author: knhor Date: Sat Dec 16 21:16:38 2006 New Revision: 3683 Modified: freeswitch/branches/knhor/trunk/src/mod/applications/mod_conference/mod_conference.c Log: 3652 - hand merged 3653 - already done 3655 - hand merged 3656 - hand merged 3666 - hand merged 3668 - hand merged 3670 - hand merged 3672 - hand merged 3676 - hand merged 3678 - hand merged 3679 - hand merged Modified: freeswitch/branches/knhor/trunk/src/mod/applications/mod_conference/mod_conference.c ============================================================================== --- freeswitch/branches/knhor/trunk/src/mod/applications/mod_conference/mod_conference.c (original) +++ freeswitch/branches/knhor/trunk/src/mod/applications/mod_conference/mod_conference.c Sat Dec 16 21:16:38 2006 @@ -137,15 +137,15 @@ NODE_TYPE_SPEECH } node_type_t; -typedef struct confernce_file_node { +typedef struct conference_file_node { switch_file_handle_t fh; switch_speech_handle_t sh; node_type_t type; uint8_t done; switch_memory_pool_t *pool; uint32_t leadin; - struct confernce_file_node *next; -} confernce_file_node_t; + struct conference_file_node *next; +} conference_file_node_t; /* conference xml config sections */ typedef struct conf_xml_cfg { @@ -187,7 +187,7 @@ switch_mutex_t *mutex; conference_member_t *members; switch_mutex_t *member_mutex; - confernce_file_node_t *fnode; + conference_file_node_t *fnode; switch_memory_pool_t *pool; switch_thread_rwlock_t *rwlock; uint32_t count; @@ -230,7 +230,7 @@ uint32_t native_rate; switch_audio_resampler_t *mux_resampler; switch_audio_resampler_t *read_resampler; - confernce_file_node_t *fnode; + conference_file_node_t *fnode; conference_relationship_t *relationships; switch_ivr_digit_stream_t *digit_stream; struct conference_member *next; @@ -507,6 +507,28 @@ last = imember; } + /* Close Unused Handles */ + if (member->fnode) { + conference_file_node_t *fnode, *cur; + switch_memory_pool_t *pool; + + fnode = member->fnode; + while(fnode) { + cur = fnode; + fnode = fnode->next; + + if (cur->type == NODE_TYPE_SPEECH) { + switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE; + switch_core_speech_close(&cur->sh, &flags); + } else { + switch_core_file_close(&cur->fh); + } + + pool = cur->pool; + switch_core_destroy_memory_pool(&pool); + } + } + member->conference = NULL; if (!switch_test_flag(member, MFLAG_NOCHANNEL)) { @@ -722,7 +744,7 @@ } if (conference->fnode && conference->fnode->done) { - confernce_file_node_t *fnode; + conference_file_node_t *fnode; switch_memory_pool_t *pool; if (conference->fnode->type == NODE_TYPE_SPEECH) { @@ -761,6 +783,29 @@ switch_mutex_lock(conference->mutex); + /* Close Unused Handles */ + if (conference->fnode) { + conference_file_node_t *fnode, *cur; + switch_memory_pool_t *pool; + + fnode = conference->fnode; + while (fnode) { + cur = fnode; + fnode = fnode->next; + + if (cur->type == NODE_TYPE_SPEECH) { + switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE; + switch_core_speech_close(&cur->sh, &flags); + } else { + switch_core_file_close(&cur->fh); + } + + pool = cur->pool; + switch_core_destroy_memory_pool(&pool); + } + conference->fnode = NULL; + } + for(imember = conference->members; imember; imember = imember->next) { switch_channel_t *channel; @@ -831,6 +876,7 @@ static void conference_loop_fn_energy_up(conference_member_t *member, void *data) { char msg[512]; + switch_event_t *event; switch_mutex_lock(member->flag_mutex); member->energy_level += 100; @@ -838,24 +884,50 @@ member->energy_level = 1200; } switch_mutex_unlock(member->flag_mutex); + snprintf(msg, sizeof(msg), "Energy level %d", member->energy_level); conference_member_say(member, msg, 0); + + if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) { + switch_channel_t *channel = switch_core_session_get_channel(member->session); + + switch_channel_event_set_data(channel, event); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Conference-Name", member->conference->name); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Member-ID", "%u", member->id); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Action", "energy-level"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "New-Level", "%d", member->energy_level); + switch_event_fire(&event); + } } static void conference_loop_fn_energy_equ_conf(conference_member_t *member, void *data) { char msg[512]; + switch_event_t *event; switch_mutex_lock(member->flag_mutex); member->energy_level = member->conference->energy_level; switch_mutex_unlock(member->flag_mutex); + snprintf(msg, sizeof(msg), "Energy level %d", member->energy_level); conference_member_say(member, msg, 0); + + if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) { + switch_channel_t *channel = switch_core_session_get_channel(member->session); + + switch_channel_event_set_data(channel, event); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Conference-Name", member->conference->name); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Member-ID", "%u", member->id); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Action", "energy-level"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "New-Level", "%d", member->energy_level); + switch_event_fire(&event); + } } static void conference_loop_fn_energy_dn(conference_member_t *member, void *data) { char msg[512]; + switch_event_t *event; switch_mutex_lock(member->flag_mutex); member->energy_level -= 100; @@ -863,78 +935,168 @@ member->energy_level = 0; } switch_mutex_unlock(member->flag_mutex); + snprintf(msg, sizeof(msg), "Energy level %d", member->energy_level); conference_member_say(member, msg, 0); + + if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) { + switch_channel_t *channel = switch_core_session_get_channel(member->session); + + switch_channel_event_set_data(channel, event); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Conference-Name", member->conference->name); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Member-ID", "%u", member->id); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Action", "energy-level"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "New-Level", "%d", member->energy_level); + switch_event_fire(&event); + } } static void conference_loop_fn_volume_talk_up(conference_member_t *member, void *data) { char msg[512]; + switch_event_t *event; switch_mutex_lock(member->flag_mutex); member->volume_out_level++; switch_normalize_volume(member->volume_out_level); switch_mutex_unlock(member->flag_mutex); + snprintf(msg, sizeof(msg), "Volume level %d", member->volume_out_level); conference_member_say(member, msg, 0); + + if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) { + switch_channel_t *channel = switch_core_session_get_channel(member->session); + + switch_channel_event_set_data(channel, event); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Conference-Name", member->conference->name); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Member-ID", "%u", member->id); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Action", "volume-level"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "New-Level", "%d", member->volume_out_level); + switch_event_fire(&event); + } } static void conference_loop_fn_volume_talk_zero(conference_member_t *member, void *data) { char msg[512]; + switch_event_t *event; switch_mutex_lock(member->flag_mutex); member->volume_out_level = 0; switch_mutex_unlock(member->flag_mutex); + snprintf(msg, sizeof(msg), "Volume level %d", member->volume_out_level); conference_member_say(member, msg, 0); + + if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) { + switch_channel_t *channel = switch_core_session_get_channel(member->session); + + switch_channel_event_set_data(channel, event); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Conference-Name", member->conference->name); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Member-ID", "%u", member->id); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Action", "volume-level"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "New-Level", "%d", member->volume_out_level); + switch_event_fire(&event); + } } static void conference_loop_fn_volume_talk_dn(conference_member_t *member, void *data) { char msg[512]; + switch_event_t *event; switch_mutex_lock(member->flag_mutex); member->volume_out_level--; switch_normalize_volume(member->volume_out_level); switch_mutex_unlock(member->flag_mutex); + snprintf(msg, sizeof(msg), "Volume level %d", member->volume_out_level); conference_member_say(member, msg, 0); + + if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) { + switch_channel_t *channel = switch_core_session_get_channel(member->session); + + switch_channel_event_set_data(channel, event); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Conference-Name", member->conference->name); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Member-ID", "%u", member->id); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Action", "volume-level"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "New-Level", "%d", member->volume_out_level); + switch_event_fire(&event); + } } static void conference_loop_fn_volume_listen_up(conference_member_t *member, void *data) { char msg[512]; + switch_event_t *event; switch_mutex_lock(member->flag_mutex); member->volume_in_level++; switch_normalize_volume(member->volume_in_level); switch_mutex_unlock(member->flag_mutex); + snprintf(msg, sizeof(msg), "Gain level %d", member->volume_in_level); conference_member_say(member, msg, 0); + + if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) { + switch_channel_t *channel = switch_core_session_get_channel(member->session); + + switch_channel_event_set_data(channel, event); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Conference-Name", member->conference->name); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Member-ID", "%u", member->id); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Action", "gain-level"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "New-Level", "%d", member->volume_in_level); + switch_event_fire(&event); + } } static void conference_loop_fn_volume_listen_zero(conference_member_t *member, void *data) { char msg[512]; + switch_event_t *event; switch_mutex_lock(member->flag_mutex); member->volume_in_level = 0; switch_mutex_unlock(member->flag_mutex); + snprintf(msg, sizeof(msg), "Gain level %d", member->volume_in_level); conference_member_say(member, msg, 0); + + if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) { + switch_channel_t *channel = switch_core_session_get_channel(member->session); + + switch_channel_event_set_data(channel, event); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Conference-Name", member->conference->name); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Member-ID", "%u", member->id); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Action", "gain-level"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "New-Level", "%d", member->volume_in_level); + switch_event_fire(&event); + } } static void conference_loop_fn_volume_listen_dn(conference_member_t *member, void *data) { char msg[512]; + switch_event_t *event; switch_mutex_lock(member->flag_mutex); member->volume_in_level--; switch_normalize_volume(member->volume_in_level); switch_mutex_unlock(member->flag_mutex); + snprintf(msg, sizeof(msg), "Gain level %d", member->volume_in_level); conference_member_say(member, msg, 0); + + if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) { + switch_channel_t *channel = switch_core_session_get_channel(member->session); + + switch_channel_event_set_data(channel, event); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Conference-Name", member->conference->name); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Member-ID", "%u", member->id); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Action", "gain-level"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "New-Level", "%d", member->volume_in_level); + switch_event_fire(&event); + } } static void conference_loop_fn_hangup(conference_member_t *member, void *data) @@ -1040,15 +1202,15 @@ int16_t *data; data = read_frame->data; - samples = read_frame->datalen / sizeof(*data); + if ((samples = read_frame->datalen / sizeof(*data))) { - for (i = 0; i < samples; i++) { - energy += abs(data[j]); - j += read_codec->implementation->number_of_channels; + for (i = 0; i < samples; i++) { + energy += abs(data[j]); + j += read_codec->implementation->number_of_channels; + } + score = energy / samples; } - score = energy / samples; - if (score > energy_level) { uint32_t diff = score - energy_level; if (hangover_hits) { @@ -1286,7 +1448,7 @@ if (member->fnode) { /* if we are done, clean it up */ if (member->fnode->done) { - confernce_file_node_t *fnode; + conference_file_node_t *fnode; switch_memory_pool_t *pool; if (member->fnode->type == NODE_TYPE_SPEECH) { @@ -1514,7 +1676,7 @@ /* Make files stop playing in a conference either the current one or all of them */ static uint32_t conference_stop_file(conference_obj_t *conference, file_stop_t stop) { - confernce_file_node_t *nptr; + conference_file_node_t *nptr; uint32_t count = 0; switch_mutex_lock(conference->mutex); @@ -1539,7 +1701,7 @@ /* stop playing a file for the member of the conference */ static uint32_t conference_member_stop_file(conference_member_t *member, file_stop_t stop) { - confernce_file_node_t *nptr; + conference_file_node_t *nptr; uint32_t count = 0; switch_mutex_lock(member->flag_mutex); @@ -1564,7 +1726,7 @@ /* Play a file in the conference room */ static switch_status_t conference_play_file(conference_obj_t *conference, char *file, uint32_t leadin, switch_channel_t *channel) { - confernce_file_node_t *fnode, *nptr; + conference_file_node_t *fnode, *nptr; switch_memory_pool_t *pool; uint32_t count; char *expanded = NULL; @@ -1651,7 +1813,7 @@ /* Play a file in the conference room to a member */ static switch_status_t conference_member_play_file(conference_member_t *member, char *file, uint32_t leadin) { - confernce_file_node_t *fnode, *nptr; + conference_file_node_t *fnode, *nptr; switch_memory_pool_t *pool; if (*file != '/') { @@ -1704,7 +1866,7 @@ static switch_status_t conference_member_say(conference_member_t *member, char *text, uint32_t leadin) { conference_obj_t *conference = (member != NULL ? member->conference : NULL); - confernce_file_node_t *fnode, *nptr; + conference_file_node_t *fnode, *nptr; switch_memory_pool_t *pool; switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE; @@ -1743,7 +1905,6 @@ return SWITCH_STATUS_FALSE; } - fnode->pool = pool; /* Queue the node */ @@ -1755,11 +1916,11 @@ } else { member->fnode = fnode; } - switch_mutex_unlock(member->flag_mutex); /* Begin Generation */ switch_sleep(200000); switch_core_speech_feed_tts(&fnode->sh, text, &flags); + switch_mutex_unlock(member->flag_mutex); return SWITCH_STATUS_SUCCESS; } @@ -1767,7 +1928,7 @@ /* Say some thing with TTS in the conference room */ static switch_status_t conference_say(conference_obj_t *conference, char *text, uint32_t leadin) { - confernce_file_node_t *fnode, *nptr; + conference_file_node_t *fnode, *nptr; switch_memory_pool_t *pool; switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE; uint32_t count; @@ -1823,11 +1984,11 @@ } else { conference->fnode = fnode; } - switch_mutex_unlock(conference->mutex); /* Begin Generation */ switch_sleep(200000); switch_core_speech_feed_tts(&fnode->sh, text, &flags); + switch_mutex_unlock(conference->mutex); return SWITCH_STATUS_SUCCESS; } @@ -1887,7 +2048,11 @@ count++; } - stream->write_function(stream, "\n"); + stream->write_function(stream, "%s%d%s%d%s%d\n", + delim, + member->volume_in_level, delim, + member->volume_out_level, delim, + member->energy_level); } switch_mutex_unlock(conference->member_mutex); } @@ -2460,7 +2625,7 @@ { int err = 0; - if (argc > 3) { + if (argc > 3 && !switch_strlen_zero(argv[2])) { int x; for (x=3; x<argc; x++) { @@ -2481,7 +2646,7 @@ /* build a new conference if it doesn't exist */ if (!(new_conference = (conference_obj_t *) switch_core_hash_find(globals.conference_hash, argv[2]))) { - switch_memory_pool_t *pool; + switch_memory_pool_t *pool = NULL; char *conf_name; conf_xml_cfg_t xml_cfg; @@ -2522,6 +2687,9 @@ if (!new_conference) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); + if (pool != NULL) { + switch_core_destroy_memory_pool(&pool); + } goto done; } @@ -2539,7 +2707,7 @@ conference_del_member(member->last_conference, member); conference_add_member(new_conference, member); - stream->write_function(stream, "OK Member %u sent to conference %s.\n", id, argv[2]); + stream->write_function(stream, "OK Members sent to conference %s.\n", argv[2]); /* tell them what happened */ if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) { @@ -2759,9 +2927,7 @@ } } - if (lbuf) { - free(lbuf); - } + switch_safe_free(lbuf); return status; @@ -3936,13 +4102,92 @@ return conference; } -/* Called by FreeSWITCH when the module loads */ +static void pres_event_handler(switch_event_t *event) +{ + char *to = switch_event_get_header(event, "to"); + char *dup_to = NULL, *conf_name, *e; + conference_obj_t *conference; + + if (!to || strncasecmp(to, "conf+", 5)) { + return; + } + + if (!(dup_to = strdup(to))) { + return; + } + + conf_name = dup_to + 5; + + if ((e = strchr(conf_name, '@'))) { + *e = '\0'; + } + + if ((conference = (conference_obj_t *) switch_core_hash_find(globals.conference_hash, conf_name))) { + switch_event_t *event; + + if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", CONF_CHAT_PROTO); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", conference->name); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", conference->name, conference->domain); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", "Active (%d caller%s)", conference->count, conference->count == 1 ? "" : "s"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); + switch_event_fire(&event); + } + } else if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", CONF_CHAT_PROTO); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", conf_name); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s", to); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", "Idle"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "rpid", "idle"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); + switch_event_fire(&event); + } + + switch_safe_free(dup_to); +} + +static void send_presence(switch_event_types_t id) +{ + switch_xml_t cxml, cfg, advertise, room; + + /* Open the config from the xml registry */ + if (!(cxml = switch_xml_open_cfg(global_cf_name, &cfg, NULL))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", global_cf_name); + goto done; + } + + if ((advertise = switch_xml_child(cfg, "advertise"))) { + for (room = switch_xml_child(advertise, "room"); room; room = room->next) { + char *name = (char *) switch_xml_attr_soft(room, "name"); + char *status = (char *) switch_xml_attr_soft(room, "status"); + switch_event_t *event; + + if (name && switch_event_create(&event, id) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", CONF_CHAT_PROTO); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", name); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s", name); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", "%s", status ? status : "Available"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "rpid", "idle"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); + switch_event_fire(&event); + } + } + } + + done: + /* Release the config registry handle */ + if (cxml) { + switch_xml_free(cxml); + cxml = NULL; + } +} + + /* Called by FreeSWITCH when the module loads */ SWITCH_MOD_DECLARE(switch_status_t) switch_module_load(const switch_loadable_module_interface_t **module_interface, char *filename) { int i; size_t nl,ol=0; char *p = NULL; - switch_status_t status = SWITCH_STATUS_SUCCESS; memset(&globals, 0, sizeof(globals)); @@ -3986,6 +4231,14 @@ switch_mutex_init(&globals.conference_mutex, SWITCH_MUTEX_NESTED, globals.conference_pool); switch_mutex_init(&globals.id_mutex, SWITCH_MUTEX_NESTED, globals.conference_pool); switch_mutex_init(&globals.hash_mutex, SWITCH_MUTEX_NESTED, globals.conference_pool); + + /* Subscribe to presence request events */ + if (switch_event_bind((char *) modname, SWITCH_EVENT_PRESENCE_PROBE, SWITCH_EVENT_SUBCLASS_ANY, pres_event_handler, NULL) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't subscribe to presence request events!\n"); + return SWITCH_STATUS_GENERR; + } + + send_presence(SWITCH_EVENT_PRESENCE_IN); globals.running = 1; /* indicate that the module should continue to be loaded */
participants (1)
-
Freeswitch SVN