]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
[core] Add switch_ivr_record_file_event() and handle execute_on_record_start/execute_...
authorChris Rienzo <chris@signalwire.com>
Tue, 22 Dec 2020 23:23:35 +0000 (18:23 -0500)
committerAndrey Volk <andywolk@gmail.com>
Sat, 23 Oct 2021 19:00:39 +0000 (22:00 +0300)
src/include/switch_ivr.h
src/switch_ivr_async.c
src/switch_ivr_play_say.c
tests/unit/switch_ivr_async.c
tests/unit/switch_ivr_play_say.c

index 1e76848dc9c071d0bd25a5373224e477f58e92d9..33fd297da87a49d2991e4200d5aaae1f0a82c422 100644 (file)
@@ -438,7 +438,19 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_gentones(switch_core_session_t *sessi
 SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(_In_ switch_core_session_t *session,
                                                                                                           _In_ switch_file_handle_t *fh,
                                                                                                           _In_z_ const char *file, _In_opt_ switch_input_args_t *args, _In_ uint32_t limit);
-
+/*!
+  \brief record a file from the session to a file
+  \param session the session to record from
+  \param fh file handle to use
+  \param file the path to the file
+  \param args arguements to pass for callbacks etc
+  \param limit max limit to record for (0 for infinite)
+  \param vars vars to add to RECORD_START and RECORD_STOP automatically prefixed with Recording-Variable-
+  \return SWITCH_STATUS_SUCCESS if all is well
+*/
+SWITCH_DECLARE(switch_status_t) switch_ivr_record_file_event(_In_ switch_core_session_t *session,
+                                                                                                          _In_ switch_file_handle_t *fh,
+                                                                                                          _In_z_ const char *file, _In_opt_ switch_input_args_t *args, _In_ uint32_t limit, switch_event_t *vars);
 
 /*!
   \brief Play a sound and gather digits with the number of retries specified if the user doesn't give digits in the set time
index 82e62cf90f40350a49d01a0736564cdb4b911c01..95bdec73523021ef9c838ad96706576c7f719721 100644 (file)
@@ -2911,7 +2911,7 @@ static switch_status_t record_helper_destroy(struct record_helper **rh, switch_c
 static const char *get_recording_var(switch_channel_t *channel, switch_event_t *vars, const char *name)
 {
        const char *val = NULL;
-       if (vars && !(val = switch_event_get_header(vars, name))) {
+       if (!vars || !(val = switch_event_get_header(vars, name))) {
                val = switch_channel_get_variable(channel, name);
        }
        return val;
index a03ab9ab5f779c010440a4ee5f71006e832b415e..49b5445b890737fb10472581561ed089cb69de3a 100644 (file)
@@ -353,8 +353,46 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_phrase_macro_event(switch_core_sessio
        return status;
 }
 
-SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *session,
-                                                                                                          switch_file_handle_t *fh, const char *file, switch_input_args_t *args, uint32_t limit)
+static void merge_recording_variables(switch_event_t *vars, switch_event_t *event)
+{
+       switch_event_header_t *hi;
+       if (vars) {
+               for (hi = vars->headers; hi; hi = hi->next) {
+                       char buf[1024];
+                       char *vvar = NULL, *vval = NULL;
+
+                       vvar = (char *) hi->name;
+                       vval = (char *) hi->value;
+
+                       switch_assert(vvar && vval);
+                       switch_snprintf(buf, sizeof(buf), "Recording-Variable-%s", vvar);
+                       switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, buf, vval);
+               }
+       }
+}
+
+static const char *get_recording_var(switch_channel_t *channel, switch_event_t *vars, switch_file_handle_t *fh, const char *name)
+{
+       const char *val = NULL;
+       if (vars) {
+               val = switch_event_get_header(vars, name);
+       }
+       if (!val && fh && fh->params) {
+               val = switch_event_get_header(fh->params, name);
+       }
+       if (!val) {
+               val = switch_channel_get_variable(channel, name);
+       }
+       return val;
+}
+
+static int recording_var_true(switch_channel_t *channel, switch_event_t *vars, switch_file_handle_t *fh, const char *name)
+{
+       return switch_true(get_recording_var(channel, vars, fh, name));
+}
+
+SWITCH_DECLARE(switch_status_t) switch_ivr_record_file_event(switch_core_session_t *session,
+                                                                                                          switch_file_handle_t *fh, const char *file, switch_input_args_t *args, uint32_t limit, switch_event_t *vars)
 {
        switch_channel_t *channel = switch_core_session_get_channel(session);
        switch_dtmf_t dtmf = { 0 };
@@ -394,7 +432,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
                return SWITCH_STATUS_FALSE;
        }
 
-       prefix = switch_channel_get_variable(channel, "sound_prefix");
+       prefix = get_recording_var(channel, vars, fh, "sound_prefix");
 
        if (!prefix) {
                prefix = SWITCH_GLOBAL_dirs.sounds_dir;
@@ -425,7 +463,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
        }
 
 
-       if ((p = switch_channel_get_variable(channel, "record_sample_rate"))) {
+       if ((p = get_recording_var(channel, vars, fh, "record_sample_rate"))) {
                int tmp = 0;
 
                tmp = atoi(p);
@@ -476,16 +514,16 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
        }
 
 
-       vval = switch_channel_get_variable(channel, "enable_file_write_buffering");
+       vval = get_recording_var(channel, vars, fh, "enable_file_write_buffering");
        if (!vval || switch_true(vval)) {
                fh->pre_buffer_datalen = SWITCH_DEFAULT_FILE_BUFFER_LEN;
        }
 
-       if (switch_test_flag(fh, SWITCH_FILE_WRITE_APPEND) || ((p = switch_channel_get_variable(channel, "RECORD_APPEND")) && switch_true(p))) {
+       if (switch_test_flag(fh, SWITCH_FILE_WRITE_APPEND) || recording_var_true(channel, vars, fh, "RECORD_APPEND")) {
                file_flags |= SWITCH_FILE_WRITE_APPEND;
        }
 
-       if (switch_test_flag(fh, SWITCH_FILE_WRITE_OVER) || ((p = switch_channel_get_variable(channel, "RECORD_WRITE_OVER")) && switch_true(p))) {
+       if (switch_test_flag(fh, SWITCH_FILE_WRITE_OVER) || recording_var_true(channel, vars, fh, "RECORD_WRITE_OVER")) {
                file_flags |= SWITCH_FILE_WRITE_OVER;
        }
 
@@ -520,7 +558,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
        }
 
 
-       if ((p = switch_channel_get_variable(channel, "record_fill_cng")) || (fh->params && (p = switch_event_get_header(fh->params, "record_fill_cng")))) {
+       if ((p = get_recording_var(channel, vars, fh, "record_fill_cng"))) {
                if (!strcasecmp(p, "true")) {
                        fill_cng = 1400;
                } else {
@@ -542,8 +580,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
                }
        }
 
-       if ((p = switch_channel_get_variable(channel, "record_waste_resources")) ||
-               (fh->params && (p = switch_event_get_header(fh->params, "record_waste_resources")))) {
+       if ((p = get_recording_var(channel, vars, fh,  "record_waste_resources"))) {
 
                if (!strcasecmp(p, "true")) {
                        waste_resources = 1400;
@@ -581,9 +618,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
        if (switch_core_file_has_video(fh, SWITCH_TRUE)) {
                switch_core_session_request_video_refresh(session);
 
-               if ((p = switch_channel_get_variable(channel, "record_play_video")) ||
-
-                       (fh->params && (p = switch_event_get_header(fh->params, "record_play_video")))) {
+               if ((p = get_recording_var(channel, vars, fh, "record_play_video"))) {
 
                        video_file = switch_core_session_strdup(session, p);
 
@@ -626,39 +661,39 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
                asis = 1;
        }
 
-       restart_limit_on_dtmf = switch_true(switch_channel_get_variable(channel, "record_restart_limit_on_dtmf"));
+       restart_limit_on_dtmf = recording_var_true(channel, vars, fh, "record_restart_limit_on_dtmf");
 
-       if ((p = switch_channel_get_variable(channel, "record_title")) || (fh->params && (p = switch_event_get_header(fh->params, "record_title")))) {
+       if ((p = get_recording_var(channel, vars, fh,  "record_title"))) {
                vval = switch_core_session_strdup(session, p);
                switch_core_file_set_string(fh, SWITCH_AUDIO_COL_STR_TITLE, vval);
                switch_channel_set_variable(channel, "record_title", NULL);
        }
 
-       if ((p = switch_channel_get_variable(channel, "record_copyright")) || (fh->params && (p = switch_event_get_header(fh->params, "record_copyright")))) {
+       if ((p = get_recording_var(channel, vars, fh, "record_copyright"))) {
                vval = switch_core_session_strdup(session, p);
                switch_core_file_set_string(fh, SWITCH_AUDIO_COL_STR_COPYRIGHT, vval);
                switch_channel_set_variable(channel, "record_copyright", NULL);
        }
 
-       if ((p = switch_channel_get_variable(channel, "record_software")) || (fh->params && (p = switch_event_get_header(fh->params, "record_software")))) {
+       if ((p = get_recording_var(channel, vars, fh, "record_software"))) {
                vval = switch_core_session_strdup(session, p);
                switch_core_file_set_string(fh, SWITCH_AUDIO_COL_STR_SOFTWARE, vval);
                switch_channel_set_variable(channel, "record_software", NULL);
        }
 
-       if ((p = switch_channel_get_variable(channel, "record_artist")) || (fh->params && (p = switch_event_get_header(fh->params, "record_artist")))) {
+       if ((p = get_recording_var(channel, vars, fh,  "record_artist"))) {
                vval = switch_core_session_strdup(session, p);
                switch_core_file_set_string(fh, SWITCH_AUDIO_COL_STR_ARTIST, vval);
                switch_channel_set_variable(channel, "record_artist", NULL);
        }
 
-       if ((p = switch_channel_get_variable(channel, "record_comment")) || (fh->params && (p = switch_event_get_header(fh->params, "record_comment")))) {
+       if ((p = get_recording_var(channel, vars, fh, "record_comment"))) {
                vval = switch_core_session_strdup(session, p);
                switch_core_file_set_string(fh, SWITCH_AUDIO_COL_STR_COMMENT, vval);
                switch_channel_set_variable(channel, "record_comment", NULL);
        }
 
-       if ((p = switch_channel_get_variable(channel, "record_date")) || (fh->params && (p = switch_event_get_header(fh->params, "record_date")))) {
+       if ((p = get_recording_var(channel, vars, fh, "record_date"))) {
                vval = switch_core_session_strdup(session, p);
                switch_core_file_set_string(fh, SWITCH_AUDIO_COL_STR_DATE, vval);
                switch_channel_set_variable(channel, "record_date", NULL);
@@ -722,9 +757,19 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
        if (switch_event_create(&event, SWITCH_EVENT_RECORD_START) == SWITCH_STATUS_SUCCESS) {
                switch_channel_event_set_data(channel, event);
                switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Record-File-Path", file);
+               merge_recording_variables(vars, event);
                switch_event_fire(&event);
        }
 
+       {
+               const char *app_exec = NULL;
+               if (vars && (app_exec = switch_event_get_header(vars, "execute_on_record_start"))) {
+                       switch_channel_execute_on_value(channel, app_exec);
+               }
+               switch_channel_execute_on(channel, "execute_on_record_start");
+               switch_channel_api_on(channel, "api_on_record_start");
+       }
+
        for (;;) {
                switch_size_t len;
 
@@ -927,9 +972,18 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
        switch_core_file_get_string(fh, SWITCH_AUDIO_COL_STR_FILE_SIZE, &file_size);
        switch_core_file_get_string(fh, SWITCH_AUDIO_COL_STR_FILE_TRIMMED, &file_trimmed);
        switch_core_file_get_string(fh, SWITCH_AUDIO_COL_STR_FILE_TRIMMED_MS, &file_trimmed_ms);
-       if (file_trimmed_ms) switch_channel_set_variable(channel, "record_record_trimmed_ms", file_trimmed_ms);
-       if (file_size) switch_channel_set_variable(channel, "record_record_file_size", file_size);
-       if (file_trimmed) switch_channel_set_variable(channel, "record_record_trimmed", file_trimmed);
+       if (file_trimmed_ms) {
+               switch_channel_set_variable(channel, "record_record_trimmed_ms", file_trimmed_ms);
+               switch_channel_set_variable(channel, "record_trimmed_ms", file_trimmed_ms);
+       }
+       if (file_size) {
+               switch_channel_set_variable(channel, "record_record_file_size", file_size);
+               switch_channel_set_variable(channel, "record_file_size", file_size);
+       }
+       if (file_trimmed) {
+               switch_channel_set_variable(channel, "record_record_trimmed", file_trimmed);
+               switch_channel_set_variable(channel, "record_trimmed", file_trimmed);
+       }
        switch_core_file_close(fh);
 
 
@@ -966,15 +1020,31 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
        if (switch_event_create(&event, SWITCH_EVENT_RECORD_STOP) == SWITCH_STATUS_SUCCESS) {
                switch_channel_event_set_data(channel, event);
                switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Record-File-Path", file);
+               merge_recording_variables(vars, event);
                switch_event_fire(&event);
        }
 
+       {
+               const char *app_exec = NULL;
+               if (vars && (app_exec = switch_event_get_header(vars, "execute_on_record_stop"))) {
+                       switch_channel_execute_on_value(channel, app_exec);
+               }
+               switch_channel_execute_on(channel, "execute_on_record_stop");
+               switch_channel_api_on(channel, "api_on_record_stop");
+       }
+
        switch_core_session_reset(session, SWITCH_TRUE, SWITCH_TRUE);
 
        arg_recursion_check_stop(args);
        return status;
 }
 
+SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *session,
+                                                                                                          switch_file_handle_t *fh, const char *file, switch_input_args_t *args, uint32_t limit)
+{
+       return switch_ivr_record_file_event(session, fh, file, args, limit, NULL);
+}
+
 static int teletone_handler(teletone_generation_session_t *ts, teletone_tone_map_t *map)
 {
        switch_buffer_t *audio_buffer = ts->user_data;
index affd47587cb16cec937969ce6cc3a2f36609e687..dedf026dd5f048c019266aabc1538498357ca23f 100644 (file)
@@ -156,6 +156,40 @@ FST_CORE_BEGIN("./conf_async")
                        switch_event_destroy(&rec_vars);
                }
                FST_SESSION_END()
+
+               FST_SESSION_BEGIN(session_record_chan_vars)
+               {
+                       const char *record_filename = switch_core_session_sprintf(fst_session, "%s%s%s.wav", SWITCH_GLOBAL_dirs.temp_dir, SWITCH_PATH_SEPARATOR, switch_core_session_get_uuid(fst_session));
+                       switch_status_t status;
+
+                       // record READ stream only- should be complete silence which will trigger the initial timeout.
+                       // Min seconds set to 2, which will cause the recording to be discarded.
+                       // Expect the record_start_test_pass and record_stop_test_pass variables set to true
+                       switch_channel_set_variable(fst_channel, "execute_on_record_start", "set record_start_test_pass=true");
+                       switch_channel_set_variable(fst_channel, "execute_on_record_stop", "set record_stop_test_pass=true");
+                       switch_channel_set_variable(fst_channel, SWITCH_RECORD_POST_PROCESS_EXEC_APP_VARIABLE, "set record_post_process_test_pass=true");
+                       switch_channel_set_variable(fst_channel, "RECORD_READ_ONLY", "true");
+                       switch_channel_set_variable(fst_channel, "RECORD_INITIAL_TIMEOUT_MS", "500");
+                       switch_channel_set_variable(fst_channel, "RECORD_MIN_SEC", "2");
+
+                       status = switch_ivr_record_session_event(fst_session, record_filename, 0, NULL, NULL);
+                       fst_xcheck(status == SWITCH_STATUS_SUCCESS, "Expect switch_ivr_record_session() to return SWITCH_STATUS_SUCCESS");
+
+                       status = switch_ivr_play_file(fst_session, NULL, "tone_stream://%(400,200,400,450);%(400,2000,400,450)", NULL);
+                       fst_xcheck(status == SWITCH_STATUS_SUCCESS, "Expect switch_ivr_play_file() to return SWITCH_STATUS_SUCCESS");
+
+                       status = switch_ivr_record_session_pause(fst_session, record_filename, SWITCH_TRUE);
+                       fst_xcheck(status != SWITCH_STATUS_SUCCESS, "Expect switch_ivr_record_session_pause(SWITCH_TRUE) not to return SWITCH_STATUS_SUCCESS because the recording has already stopped");
+
+                       fst_xcheck(switch_file_exists(record_filename, fst_pool) != SWITCH_STATUS_SUCCESS, "Expect recording file not to exist since it was less than 2 seconds in duration");
+
+                       fst_xcheck(switch_channel_var_true(fst_channel, "record_start_test_pass"), "Expect record_start_test_pass channel variable set to true");
+                       fst_xcheck(switch_channel_var_true(fst_channel, "record_stop_test_pass"), "Expect record_stop_test_pass channel variable set to true");
+                       fst_xcheck(switch_channel_var_true(fst_channel, "record_post_process_test_pass"), "Expect record_post_process_test_pass channel variable set to true");
+
+                       unlink(record_filename);
+               }
+               FST_SESSION_END()
        }
        FST_SUITE_END()
 }
index 1d0bab84f1c41c5214e63e7257837a8d407c9ba0..3e2ded6aff5c32d076b9f15445ef4e4c2d15016a 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
- * Copyright (C) 2005-2019, Anthony Minessale II <anthm@freeswitch.org>
+ * Copyright (C) 2005-2020, Anthony Minessale II <anthm@freeswitch.org>
  *
  * Version: MPL 1.1
  *
 
 #include <test/switch_test.h>
 
+static void on_record_start(switch_event_t *event)
+{
+       char *str = NULL;
+       switch_event_serialize(event, &str, SWITCH_FALSE);
+       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s", str);
+       switch_safe_free(str);
+       const char *uuid = switch_event_get_header(event, "Unique-ID");
+       if (uuid) {
+               switch_core_session_t *session = switch_core_session_locate(uuid);
+               if (session) {
+                       switch_channel_t *channel = switch_core_session_get_channel(session);
+                       const char *recording_id = switch_event_get_header_nil(event, "Recording-Variable-ID");
+                       if (!strcmp(recording_id, "foo")) {
+                               switch_channel_set_variable(channel, "record_start_event_test_pass", "true");
+                       }
+                       switch_core_session_rwunlock(session);
+               }
+       }
+}
+
+static void on_record_stop(switch_event_t *event)
+{
+       char *str = NULL;
+       switch_event_serialize(event, &str, SWITCH_FALSE);
+       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s", str);
+       switch_safe_free(str);
+       const char *uuid = switch_event_get_header(event, "Unique-ID");
+       if (uuid) {
+               switch_core_session_t *session = switch_core_session_locate(uuid);
+               if (session) {
+                       switch_channel_t *channel = switch_core_session_get_channel(session);
+                       const char *recording_id = switch_event_get_header_nil(event, "Recording-Variable-ID");
+                       if (!strcmp(recording_id, "foo")) {
+                               switch_channel_set_variable(channel, "record_stop_event_test_pass", "true");
+                       }
+                       switch_core_session_rwunlock(session);
+               }
+       }
+}
+
 static switch_status_t partial_play_and_collect_input_callback(switch_core_session_t *session, void *input, switch_input_type_t input_type, void *data, __attribute__((unused))unsigned int len)
 {
        switch_status_t status = SWITCH_STATUS_SUCCESS;
@@ -360,6 +400,79 @@ FST_CORE_BEGIN("./conf_playsay")
                        cJSON_Delete(recognition_result);
                }
                FST_SESSION_END()
+
+               FST_SESSION_BEGIN(record_file_event_vars)
+               {
+                       const char *record_filename = switch_core_session_sprintf(fst_session, "%s" SWITCH_PATH_SEPARATOR "record_file_event_vars-tmp-%s.wav", SWITCH_GLOBAL_dirs.temp_dir, switch_core_session_get_uuid(fst_session));
+                       switch_event_t *rec_vars = NULL;
+                       switch_status_t status;
+                       switch_event_create_subclass(&rec_vars, SWITCH_EVENT_CLONE, SWITCH_EVENT_SUBCLASS_ANY);
+                       fst_requires(rec_vars);
+                       switch_event_bind("record_file_event", SWITCH_EVENT_RECORD_START, SWITCH_EVENT_SUBCLASS_ANY, on_record_start, NULL);
+                       switch_event_bind("record_file_event", SWITCH_EVENT_RECORD_STOP, SWITCH_EVENT_SUBCLASS_ANY, on_record_stop, NULL);
+                       switch_event_add_header_string(rec_vars, SWITCH_STACK_BOTTOM, "execute_on_record_start", "set record_start_test_pass=true");
+                       switch_event_add_header_string(rec_vars, SWITCH_STACK_BOTTOM, "execute_on_record_stop", "set record_stop_test_pass=true");
+                       switch_event_add_header_string(rec_vars, SWITCH_STACK_BOTTOM, "ID", "foo");
+                       switch_ivr_displace_session(fst_session, "file_string://silence_stream://500,0!tone_stream://%%(2000,0,350,440)", 0, "r");
+                       status = switch_ivr_record_file_event(fst_session, NULL, record_filename, NULL, 4, rec_vars);
+                       fst_check(status == SWITCH_STATUS_SUCCESS);
+                       fst_xcheck(switch_channel_var_true(fst_channel, "record_start_test_pass"), "Expect record_start_test_pass channel variable set to true");
+                       fst_xcheck(switch_channel_var_true(fst_channel, "record_stop_test_pass"), "Expect record_stop_test_pass channel variable set to true");
+                       switch_sleep(1000 * 1000);
+                       fst_xcheck(switch_channel_var_true(fst_channel, "record_start_event_test_pass"), "Expect RECORD_START event received with Recording-Variable-ID set");
+                       fst_xcheck(switch_channel_var_true(fst_channel, "record_stop_event_test_pass"), "Expect RECORD_STOP event received with Recording-Variable-ID set");
+                       switch_event_unbind_callback(on_record_start);
+                       switch_event_unbind_callback(on_record_stop);
+                       switch_event_destroy(&rec_vars);
+                       fst_xcheck(switch_file_exists(record_filename, fst_pool) == SWITCH_STATUS_SUCCESS, "Expect recording file to exist");
+                       unlink(record_filename);
+               }
+               FST_SESSION_END()
+
+               FST_SESSION_BEGIN(record_file_event_chan_vars)
+               {
+                       const char *record_filename = switch_core_session_sprintf(fst_session, "%s" SWITCH_PATH_SEPARATOR "record_file_event_chan_vars-tmp-%s.wav", SWITCH_GLOBAL_dirs.temp_dir, switch_core_session_get_uuid(fst_session));
+                       switch_event_t *rec_vars = NULL;
+                       switch_status_t status;
+                       switch_event_create_subclass(&rec_vars, SWITCH_EVENT_CLONE, SWITCH_EVENT_SUBCLASS_ANY);
+                       fst_requires(rec_vars);
+                       switch_event_bind("record_file_event", SWITCH_EVENT_RECORD_START, SWITCH_EVENT_SUBCLASS_ANY, on_record_start, NULL);
+                       switch_event_bind("record_file_event", SWITCH_EVENT_RECORD_STOP, SWITCH_EVENT_SUBCLASS_ANY, on_record_stop, NULL);
+                       switch_channel_set_variable(fst_channel, "execute_on_record_start_1", "set record_start_test_pass=true");
+                       switch_channel_set_variable(fst_channel, "execute_on_record_stop_1", "set record_stop_test_pass=true");
+                       switch_event_add_header_string(rec_vars, SWITCH_STACK_BOTTOM, "ID", "foo");
+                       switch_ivr_displace_session(fst_session, "file_string://silence_stream://500,0!tone_stream://%%(2000,0,350,440)", 0, "r");
+                       status = switch_ivr_record_file_event(fst_session, NULL, record_filename, NULL, 4, rec_vars);
+                       fst_check(status == SWITCH_STATUS_SUCCESS);
+                       fst_xcheck(switch_channel_var_true(fst_channel, "record_start_test_pass"), "Expect record_start_test_pass channel variable set to true");
+                       fst_xcheck(switch_channel_var_true(fst_channel, "record_stop_test_pass"), "Expect record_stop_test_pass channel variable set to true");
+                       switch_sleep(1000 * 1000);
+                       fst_xcheck(switch_channel_var_true(fst_channel, "record_start_event_test_pass"), "Expect RECORD_START event received with Recording-Variable-ID set");
+                       fst_xcheck(switch_channel_var_true(fst_channel, "record_stop_event_test_pass"), "Expect RECORD_STOP event received with Recording-Variable-ID set");
+                       switch_event_unbind_callback(on_record_start);
+                       switch_event_unbind_callback(on_record_stop);
+                       switch_event_destroy(&rec_vars);
+                       fst_xcheck(switch_file_exists(record_filename, fst_pool) == SWITCH_STATUS_SUCCESS, "Expect recording file to exist");
+                       unlink(record_filename);
+               }
+               FST_SESSION_END()
+
+               FST_SESSION_BEGIN(record_file_event_chan_vars_only)
+               {
+                       const char *record_filename = switch_core_session_sprintf(fst_session, "%s" SWITCH_PATH_SEPARATOR "record_file_event_chan_vars-tmp-%s.wav", SWITCH_GLOBAL_dirs.temp_dir, switch_core_session_get_uuid(fst_session));
+                       switch_status_t status;
+                       switch_channel_set_variable(fst_channel, "execute_on_record_start_1", "set record_start_test_pass=true");
+                       switch_channel_set_variable(fst_channel, "execute_on_record_stop_1", "set record_stop_test_pass=true");
+                       switch_ivr_displace_session(fst_session, "file_string://silence_stream://500,0!tone_stream://%%(2000,0,350,440)", 0, "r");
+                       status = switch_ivr_record_file_event(fst_session, NULL, record_filename, NULL, 4, NULL);
+                       fst_check(status == SWITCH_STATUS_SUCCESS);
+                       fst_xcheck(switch_channel_var_true(fst_channel, "record_start_test_pass"), "Expect record_start_test_pass channel variable set to true");
+                       fst_xcheck(switch_channel_var_true(fst_channel, "record_stop_test_pass"), "Expect record_stop_test_pass channel variable set to true");
+                       switch_sleep(1000 * 1000);
+                       fst_xcheck(switch_file_exists(record_filename, fst_pool) == SWITCH_STATUS_SUCCESS, "Expect recording file to exist");
+                       unlink(record_filename);
+               }
+               FST_SESSION_END()
        }
        FST_SUITE_END()
 }