diff --git a/src/include/switch_core.h b/src/include/switch_core.h index d597c601a3..cb29c6a9f7 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -1943,6 +1943,12 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_set_string(_In_ switch_file_han */ SWITCH_DECLARE(switch_status_t) switch_core_file_get_string(_In_ switch_file_handle_t *fh, switch_audio_col_t col, const char **string); +/*! + \brief Pre close an open file handle, then can get file size etc., no more wirte to the file + \param fh the file handle to close + \return SWITCH_STATUS_SUCCESS if the file handle was pre closed +*/ +SWITCH_DECLARE(switch_status_t) switch_core_file_pre_close(_In_ switch_file_handle_t *fh); /*! \brief Close an open file handle diff --git a/src/include/switch_module_interfaces.h b/src/include/switch_module_interfaces.h index 067660253f..798695d090 100644 --- a/src/include/switch_module_interfaces.h +++ b/src/include/switch_module_interfaces.h @@ -298,6 +298,8 @@ struct switch_file_interface { switch_status_t (*file_set_string) (switch_file_handle_t *fh, switch_audio_col_t col, const char *string); /*! function to get meta data */ switch_status_t (*file_get_string) (switch_file_handle_t *fh, switch_audio_col_t col, const char **string); + /*! function to pre close the file to read params */ + switch_status_t (*file_pre_close) (switch_file_handle_t *fh); /*! function to control the underlying tech of the file */ switch_status_t (*file_command) (switch_file_handle_t *fh, switch_file_command_t command); /*! list of supported file extensions */ diff --git a/src/include/switch_types.h b/src/include/switch_types.h index a85d7be59a..c1d48cbd80 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -583,12 +583,22 @@ typedef enum { typedef uint32_t switch_caller_profile_flag_t; typedef enum { + // flags matching libsndfile SWITCH_AUDIO_COL_STR_TITLE = 0x01, SWITCH_AUDIO_COL_STR_COPYRIGHT = 0x02, SWITCH_AUDIO_COL_STR_SOFTWARE = 0x03, SWITCH_AUDIO_COL_STR_ARTIST = 0x04, SWITCH_AUDIO_COL_STR_COMMENT = 0x05, - SWITCH_AUDIO_COL_STR_DATE = 0x06 + SWITCH_AUDIO_COL_STR_DATE = 0x06, + SWITCH_AUDIO_COL_STR_ALBUM = 0x07, + SWITCH_AUDIO_COL_STR_LICENSE = 0x08, + SWITCH_AUDIO_COL_STR_TRACKNUMBER = 0x09, + SWITCH_AUDIO_COL_STR_GENRE = 0x10, + + // custom flags + SWITCH_AUDIO_COL_STR_FILE_SIZE = 0xF0, + SWITCH_AUDIO_COL_STR_FILE_TRIMMED = 0xF1, + SWITCH_AUDIO_COL_STR_FILE_TRIMMED_MS = 0xF2 } switch_audio_col_t; typedef enum { diff --git a/src/mod/applications/mod_conference/conference_record.c b/src/mod/applications/mod_conference/conference_record.c index e54c8fcb96..c02bb3bcff 100644 --- a/src/mod/applications/mod_conference/conference_record.c +++ b/src/mod/applications/mod_conference/conference_record.c @@ -167,6 +167,9 @@ void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *thread, v switch_size_t len = 0; int flags = 0; mcu_canvas_t *canvas = NULL; + const char *file_size = NULL; + const char *file_trimmed = NULL; + const char *file_trimmed_ms = NULL; if (switch_thread_rwlock_tryrdlock(conference->rwlock) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Read Lock Fail\n"); @@ -412,10 +415,15 @@ void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *thread, v if (switch_test_flag((&member->rec->fh), SWITCH_FILE_OPEN)) { switch_mutex_lock(conference->mutex); switch_mutex_unlock(conference->mutex); + switch_core_file_pre_close(&member->rec->fh); + switch_core_file_get_string(&member->rec->fh, SWITCH_AUDIO_COL_STR_FILE_SIZE, &file_size); + switch_core_file_get_string(&member->rec->fh, SWITCH_AUDIO_COL_STR_FILE_TRIMMED, &file_trimmed); + switch_core_file_get_string(&member->rec->fh, SWITCH_AUDIO_COL_STR_FILE_TRIMMED_MS, &file_trimmed_ms); switch_core_file_close(&member->rec->fh); } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Recording of %s Stopped\n", rec->path); + if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) { conference_event_add_data(conference, event); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "stop-recording"); @@ -424,6 +432,15 @@ void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *thread, v switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Samples-Out", "%ld", (long) member->rec->fh.samples_out); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Samplerate", "%ld", (long) member->rec->fh.samplerate); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Milliseconds-Elapsed", "%ld", (long) member->rec->fh.samples_out / (member->rec->fh.samplerate / 1000)); + + if (file_trimmed_ms) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Milliseconds-File-Trimmed", "%s", file_trimmed_ms); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Record-File-Duration", "%d", atoi(file_trimmed_ms)/1000); + } + + if (file_size) switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Record-File-Size", "%s", file_size); + if (file_trimmed) switch_event_add_header(event, SWITCH_STACK_BOTTOM, "File-Trimmed", "%s", file_trimmed); + switch_event_fire(&event); } diff --git a/src/switch_core_file.c b/src/switch_core_file.c index 9916c40f8b..4cd4600c48 100644 --- a/src/switch_core_file.c +++ b/src/switch_core_file.c @@ -36,6 +36,30 @@ #include #include "private/switch_core_pvt.h" + +static switch_status_t get_file_size(switch_file_handle_t *fh, const char **string) +{ + switch_status_t status; + switch_file_t *newfile; + switch_size_t size = 0; + + status = switch_file_open(&newfile, fh->spool_path ? fh->spool_path : fh->file_path, SWITCH_FOPEN_READ, SWITCH_FPROT_OS_DEFAULT, fh->memory_pool); + + if (status != SWITCH_STATUS_SUCCESS) { + return status; + } + + size = switch_file_get_size(newfile); + + if (size) { + *string = switch_core_sprintf(fh->memory_pool, "%" SWITCH_SIZE_T_FMT, size); + } + + status = switch_file_close(newfile); + + return status; +} + SWITCH_DECLARE(switch_status_t) switch_core_perform_file_open(const char *file, const char *func, int line, switch_file_handle_t *fh, const char *file_path, @@ -755,18 +779,32 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_set_string(switch_file_handle_t SWITCH_DECLARE(switch_status_t) switch_core_file_get_string(switch_file_handle_t *fh, switch_audio_col_t col, const char **string) { + switch_status_t status; + switch_assert(fh != NULL); switch_assert(fh->file_interface != NULL); - if (!switch_test_flag(fh, SWITCH_FILE_OPEN)) { + if (!switch_test_flag(fh, SWITCH_FILE_OPEN) && col < SWITCH_AUDIO_COL_STR_FILE_SIZE) { return SWITCH_STATUS_FALSE; } if (!fh->file_interface->file_get_string) { + if (col == SWITCH_AUDIO_COL_STR_FILE_SIZE) { + return get_file_size(fh, string); + } + return SWITCH_STATUS_FALSE; } - return fh->file_interface->file_get_string(fh, col, string); + status = fh->file_interface->file_get_string(fh, col, string); + + if (status == SWITCH_STATUS_SUCCESS && string) return status; + + if (col == SWITCH_AUDIO_COL_STR_FILE_SIZE) { + return get_file_size(fh, string); + } + + return status; } SWITCH_DECLARE(switch_status_t) switch_core_file_truncate(switch_file_handle_t *fh, int64_t offset) @@ -829,17 +867,20 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_command(switch_file_handle_t *f return status; } - -SWITCH_DECLARE(switch_status_t) switch_core_file_close(switch_file_handle_t *fh) +SWITCH_DECLARE(switch_status_t) switch_core_file_pre_close(switch_file_handle_t *fh) { - switch_status_t status; + switch_status_t status = SWITCH_STATUS_SUCCESS; switch_assert(fh != NULL); - if (!fh->file_interface || !switch_test_flag(fh, SWITCH_FILE_OPEN)) { + if (!fh->file_interface) { return SWITCH_STATUS_FALSE; } + if (!switch_test_flag(fh, SWITCH_FILE_OPEN)) { + return SWITCH_STATUS_SUCCESS; + } + if (fh->pre_buffer) { if (switch_test_flag(fh, SWITCH_FILE_FLAG_WRITE)) { switch_size_t rlen, blen; @@ -863,7 +904,23 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_close(switch_file_handle_t *fh) } switch_clear_flag_locked(fh, SWITCH_FILE_OPEN); - status = fh->file_interface->file_close(fh); + + if (fh->file_interface->file_pre_close) { + status = fh->file_interface->file_pre_close(fh); + } + + return status; +} + +SWITCH_DECLARE(switch_status_t) switch_core_file_close(switch_file_handle_t *fh) +{ + switch_status_t status = SWITCH_STATUS_SUCCESS; + + if (switch_test_flag(fh, SWITCH_FILE_OPEN)) { + status = switch_core_file_pre_close(fh); + } + + fh->file_interface->file_close(fh); if (fh->params) { switch_event_destroy(&fh->params);