diff --git a/mod_amd.c b/mod_amd.c index cccfad6..82b4ee3 100644 --- a/mod_amd.c +++ b/mod_amd.c @@ -19,7 +19,20 @@ static struct { uint32_t silence_threshold; uint32_t maximum_word_length; } globals; - +enum amd_event +{ + AMD_EVENT_HUMAN = 0, + AMD_EVENT_MACHINE = 1, + AMD_EVENT_NOTSURE = 2 +}; +/* This array MUST be NULL terminated! */ +const char* amd_events_str[] = { + [AMD_EVENT_HUMAN] = "amd::human", + [AMD_EVENT_MACHINE] = "amd::machine", + [AMD_EVENT_NOTSURE] = "amd::notsure", + NULL /* MUST be last and always here */ +}; +static void amd_fire_event(enum amd_event type, switch_core_session_t *fs_s); static switch_xml_config_item_t instructions[] = { SWITCH_CONFIG_ITEM( "initial_silence", @@ -95,7 +108,43 @@ static switch_xml_config_item_t instructions[] = { SWITCH_CONFIG_ITEM_END() }; - +static void amd_fire_event(enum amd_event type, switch_core_session_t *fs_s) { + + switch_event_t *event; + switch_event_t *event_copy; + switch_status_t status; + status = switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, amd_events_str[type]); + if (status != SWITCH_STATUS_SUCCESS) { + return; + } + + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Unique-ID", switch_core_session_get_uuid(fs_s)); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Call-command", "amd"); + + switch (type) + { + case AMD_EVENT_HUMAN: + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Amd-Status", "HUMAN"); + break; + + case AMD_EVENT_MACHINE: + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Amd-Status", "MACHINE"); + break; + case AMD_EVENT_NOTSURE: + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Amd-Status", "NOTSURE"); + break; + + default: + switch_event_destroy(&event); + return; + } + if ((switch_event_dup(&event_copy, event)) != SWITCH_STATUS_SUCCESS) { + return; + } + switch_core_session_queue_event(fs_s, &event); + switch_event_fire(&event_copy); + return; +} static switch_status_t do_config(switch_bool_t reload) { memset(&globals, 0, sizeof(globals)); @@ -181,7 +230,7 @@ static amd_frame_classifier classify_frame(const switch_frame_t *f, const switch return SILENCE; } -static switch_bool_t amd_handle_silence_frame(amd_vad_t *vad, const switch_frame_t *f) +static switch_bool_t amd_handle_silence_frame(amd_vad_t *vad, const switch_frame_t *f, switch_core_session_t *fs_s) { vad->silence_duration += vad->frame_ms; @@ -204,7 +253,7 @@ static switch_bool_t amd_handle_silence_frame(amd_vad_t *vad, const switch_frame "AMD: MACHINE (silence_duration: %d, initial_silence: %d)\n", vad->silence_duration, globals.initial_silence); - + amd_fire_event(AMD_EVENT_MACHINE, fs_s); switch_channel_set_variable(vad->channel, "amd_result", "MACHINE"); switch_channel_set_variable(vad->channel, "amd_cause", "INITIALSILENCE"); return SWITCH_TRUE; @@ -217,7 +266,7 @@ static switch_bool_t amd_handle_silence_frame(amd_vad_t *vad, const switch_frame "AMD: HUMAN (silence_duration: %d, after_greeting_silence: %d)\n", vad->silence_duration, globals.after_greeting_silence); - + amd_fire_event(AMD_EVENT_HUMAN, fs_s); switch_channel_set_variable(vad->channel, "amd_result", "HUMAN"); switch_channel_set_variable(vad->channel, "amd_cause", "HUMAN"); return SWITCH_TRUE; @@ -226,7 +275,7 @@ static switch_bool_t amd_handle_silence_frame(amd_vad_t *vad, const switch_frame return SWITCH_FALSE; } -static switch_bool_t amd_handle_voiced_frame(amd_vad_t *vad, const switch_frame_t *f) +static switch_bool_t amd_handle_voiced_frame(amd_vad_t *vad, const switch_frame_t *f, switch_core_session_t *fs_s) { vad->voice_duration += vad->frame_ms; @@ -249,7 +298,7 @@ static switch_bool_t amd_handle_voiced_frame(amd_vad_t *vad, const switch_frame_ "AMD: MACHINE (voice_duration: %d, maximum_word_length: %d)\n", vad->voice_duration, globals.maximum_word_length); - + amd_fire_event(AMD_EVENT_MACHINE, fs_s); switch_channel_set_variable(vad->channel, "amd_result", "MACHINE"); switch_channel_set_variable(vad->channel, "amd_cause", "MAXWORDLENGTH"); return SWITCH_TRUE; @@ -262,7 +311,7 @@ static switch_bool_t amd_handle_voiced_frame(amd_vad_t *vad, const switch_frame_ "AMD: MACHINE (words: %d, maximum_number_of_words: %d)\n", vad->words, globals.maximum_number_of_words); - + amd_fire_event(AMD_EVENT_MACHINE, fs_s); switch_channel_set_variable(vad->channel, "amd_result", "MACHINE"); switch_channel_set_variable(vad->channel, "amd_cause", "MAXWORDS"); return SWITCH_TRUE; @@ -275,7 +324,7 @@ static switch_bool_t amd_handle_voiced_frame(amd_vad_t *vad, const switch_frame_ "AMD: MACHINE (voice_duration: %d, greeting: %d)\n", vad->voice_duration, globals.greeting); - + amd_fire_event(AMD_EVENT_MACHINE, fs_s); switch_channel_set_variable(vad->channel, "amd_result", "MACHINE"); switch_channel_set_variable(vad->channel, "amd_cause", "LONGGREETING"); return SWITCH_TRUE; @@ -387,7 +436,7 @@ SWITCH_STANDARD_APP(amd_start_function) sample_count_limit -= raw_codec.implementation->samples_per_packet; if (sample_count_limit <= 0) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "AMD: Timeout\n"); - + amd_fire_event(AMD_EVENT_NOTSURE, session); switch_channel_set_variable(channel, "amd_result", "NOTSURE"); switch_channel_set_variable(channel, "amd_cause", "TOOLONG"); break; @@ -401,7 +450,7 @@ SWITCH_STANDARD_APP(amd_start_function) SWITCH_LOG_DEBUG, "AMD: Silence\n"); - if (amd_handle_silence_frame(&vad, read_frame)) { + if (amd_handle_silence_frame(&vad, read_frame, session)) { complete = SWITCH_TRUE; } break; @@ -412,7 +461,7 @@ SWITCH_STANDARD_APP(amd_start_function) SWITCH_LOG_DEBUG, "AMD: Voiced\n"); - if (amd_handle_voiced_frame(&vad, read_frame)) { + if (amd_handle_voiced_frame(&vad, read_frame, session)) { complete = SWITCH_TRUE; } break;