/** * Seek file */ static switch_status_t fileman_file_seek(switch_file_handle_t *handle, unsigned int *cur_sample, int64_t samples, int whence) { struct fileman_file_context *context = handle->private_info; if (!handle->seekable) { switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_WARNING, "File is not seekable\n"); return SWITCH_STATUS_NOTIMPL; } return switch_core_file_seek(&context->fh, cur_sample, samples, whence); }
/** * Seek file */ static switch_status_t ssml_file_seek(switch_file_handle_t *handle, unsigned int *cur_sample, int64_t samples, int whence) { struct ssml_context *context = handle->private_info; if (samples == 0 && whence == SWITCH_SEEK_SET) { /* restart from beginning */ context->index = -1; return next_file(handle); } if (!handle->seekable) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "File is not seekable\n"); return SWITCH_STATUS_NOTIMPL; } return switch_core_file_seek(&context->fh, cur_sample, samples, whence); }
/** * Wraps file with interface that can be controlled by fileman flags * @param handle * @param path the file to play * @return SWITCH_STATUS_SUCCESS if opened */ static switch_status_t fileman_file_open(switch_file_handle_t *handle, const char *path) { int start_offset_ms = 0; switch_status_t status = SWITCH_STATUS_FALSE; struct fileman_file_context *context = switch_core_alloc(handle->memory_pool, sizeof(*context)); handle->private_info = context; if (handle->params) { const char *id = switch_event_get_header(handle->params, "id"); const char *uuid = switch_event_get_header(handle->params, "session"); const char *start_offset_ms_str = switch_event_get_header(handle->params, "start_offset_ms"); if (!zstr(id)) { context->id = switch_core_strdup(handle->memory_pool, id); } if (!zstr(uuid)) { context->uuid = switch_core_strdup(handle->memory_pool, uuid); } if (!zstr(start_offset_ms_str) && switch_is_number(start_offset_ms_str)) { start_offset_ms = atoi(start_offset_ms_str); if (start_offset_ms < 0) { start_offset_ms = 0; } } } switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "Got path %s\n", path); if ((status = switch_core_file_open(&context->fh, path, handle->channels, handle->samplerate, handle->flags, NULL)) != SWITCH_STATUS_SUCCESS) { return status; } /* set up handle for external control */ if (!context->id) { /* use filename as ID */ context->id = switch_core_strdup(handle->memory_pool, path); } switch_mutex_lock(fileman_globals.mutex); if (!switch_core_hash_find(fileman_globals.hash, context->id)) { switch_core_hash_insert(fileman_globals.hash, context->id, handle); } else { switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_WARNING, "Duplicate fileman ID: %s\n", context->id); return SWITCH_STATUS_FALSE; } switch_mutex_unlock(fileman_globals.mutex); context->max_frame_len = (handle->samplerate / 1000 * SWITCH_MAX_INTERVAL); switch_zmalloc(context->abuf, FILE_STARTBYTES * sizeof(*context->abuf)); if (!context->fh.audio_buffer) { switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "Create audio buffer\n"); switch_buffer_create_dynamic(&context->fh.audio_buffer, FILE_BLOCKSIZE, FILE_BUFSIZE, 0); switch_assert(context->fh.audio_buffer); } handle->samples = context->fh.samples; handle->format = context->fh.format; handle->sections = context->fh.sections; handle->seekable = context->fh.seekable; handle->speed = context->fh.speed; handle->vol = context->fh.vol; handle->offset_pos = context->fh.offset_pos; handle->interval = context->fh.interval; if (switch_test_flag((&context->fh), SWITCH_FILE_NATIVE)) { switch_set_flag(handle, SWITCH_FILE_NATIVE); } else { switch_clear_flag(handle, SWITCH_FILE_NATIVE); } if (handle->params && switch_true(switch_event_get_header(handle->params, "pause"))) { switch_set_flag(handle, SWITCH_FILE_PAUSE); } if (handle->seekable && start_offset_ms) { unsigned int pos = 0; int32_t target = start_offset_ms * (handle->samplerate / 1000); switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "seek to position %d\n", target); switch_core_file_seek(&context->fh, &pos, target, SEEK_SET); } return status; }
/** * Process fileman command */ static switch_status_t fileman_process_cmd(const char *cmd, switch_file_handle_t *fhp) { if (zstr(cmd)) { return SWITCH_STATUS_SUCCESS; } if (fhp) { struct fileman_file_context *context = (struct fileman_file_context *)fhp->private_info; if (!switch_test_flag(fhp, SWITCH_FILE_OPEN)) { return SWITCH_STATUS_FALSE; } if (!strncasecmp(cmd, "speed", 5)) { char *p; if ((p = strchr(cmd, ':'))) { p++; if (*p == '+' || *p == '-') { int step; if (!(step = atoi(p))) { if (*p == '+') { step = 1; } else { step = -1; } } fhp->speed += step; } else { int speed = atoi(p); fhp->speed = speed; } return SWITCH_STATUS_SUCCESS; } return SWITCH_STATUS_FALSE; } else if (!strncasecmp(cmd, "volume", 6)) { char *p; if ((p = strchr(cmd, ':'))) { p++; if (*p == '+' || *p == '-') { int step; if (!(step = atoi(p))) { if (*p == '+') { step = 1; } else { step = -1; } } fhp->vol += step; } else { int vol = atoi(p); fhp->vol = vol; } return SWITCH_STATUS_SUCCESS; } if (fhp->vol) { switch_normalize_volume(fhp->vol); } return SWITCH_STATUS_FALSE; } else if (!strcasecmp(cmd, "pause")) { switch_set_flag(fhp, SWITCH_FILE_PAUSE); return SWITCH_STATUS_SUCCESS; } else if (!strcasecmp(cmd, "resume")) { switch_clear_flag(fhp, SWITCH_FILE_PAUSE); return SWITCH_STATUS_SUCCESS; } else if (!strcasecmp(cmd, "stop")) { switch_set_flag(fhp, SWITCH_FILE_DONE); return SWITCH_STATUS_FALSE; } else if (!strcasecmp(cmd, "truncate")) { switch_core_file_truncate(fhp, 0); } else if (!strcasecmp(cmd, "restart")) { unsigned int pos = 0; fhp->speed = 0; switch_core_file_seek(fhp, &pos, 0, SEEK_SET); return SWITCH_STATUS_SUCCESS; } else if (!strncasecmp(cmd, "seek", 4)) { unsigned int samps = 0; unsigned int pos = 0; char *p; if ((p = strchr(cmd, ':'))) { p++; if (*p == '+' || *p == '-') { int step; int32_t target; if (!(step = atoi(p))) { if (*p == '+') { step = 1000; } else { step = -1000; } } samps = step * (fhp->samplerate / 1000); target = (int32_t)fhp->pos + samps; if (target < 0) { target = 0; } switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "seek to position %d\n", target); switch_core_file_seek(fhp, &pos, target, SEEK_SET); } else { samps = switch_atoui(p) * (fhp->samplerate / 1000); switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "seek to position %d\n", samps); switch_core_file_seek(fhp, &pos, samps, SEEK_SET); } } return SWITCH_STATUS_SUCCESS; } } if (!strcmp(cmd, "true") || !strcmp(cmd, "undefined")) { return SWITCH_STATUS_SUCCESS; } return SWITCH_STATUS_FALSE; }
SWITCH_DECLARE(switch_status_t) CoreSession::process_callback_result(char *result) { this_check(SWITCH_STATUS_FALSE); sanity_check(SWITCH_STATUS_FALSE); if (zstr(result)) { return SWITCH_STATUS_SUCCESS; } if (fhp) { if (!switch_test_flag(fhp, SWITCH_FILE_OPEN)) { return SWITCH_STATUS_FALSE; } if (!strncasecmp(result, "speed", 5)) { char *p; if ((p = strchr(result, ':'))) { p++; if (*p == '+' || *p == '-') { int step; if (!(step = atoi(p))) { step = 1; } fhp->speed += step; } else { int speed = atoi(p); fhp->speed = speed; } return SWITCH_STATUS_SUCCESS; } return SWITCH_STATUS_FALSE; } else if (!strncasecmp(result, "volume", 6)) { char *p; if ((p = strchr(result, ':'))) { p++; if (*p == '+' || *p == '-') { int step; if (!(step = atoi(p))) { step = 1; } fhp->vol += step; } else { int vol = atoi(p); fhp->vol = vol; } return SWITCH_STATUS_SUCCESS; } if (fhp->vol) { switch_normalize_volume(fhp->vol); } return SWITCH_STATUS_FALSE; } else if (!strcasecmp(result, "pause")) { if (switch_test_flag(fhp, SWITCH_FILE_PAUSE)) { switch_clear_flag(fhp, SWITCH_FILE_PAUSE); } else { switch_set_flag(fhp, SWITCH_FILE_PAUSE); } return SWITCH_STATUS_SUCCESS; } else if (!strcasecmp(result, "stop")) { return SWITCH_STATUS_FALSE; } else if (!strcasecmp(result, "truncate")) { switch_core_file_truncate(fhp, 0); } else if (!strcasecmp(result, "restart")) { unsigned int pos = 0; fhp->speed = 0; switch_core_file_seek(fhp, &pos, 0, SEEK_SET); return SWITCH_STATUS_SUCCESS; } else if (!strncasecmp(result, "seek", 4)) { switch_codec_t *codec; unsigned int samps = 0; unsigned int pos = 0; char *p; codec = switch_core_session_get_read_codec(session); if ((p = strchr(result, ':'))) { p++; if (*p == '+' || *p == '-') { int step; int32_t target; if (!(step = atoi(p))) { step = 1000; } samps = step * (codec->implementation->samples_per_second / 1000); target = (int32_t)fhp->pos + samps; if (target < 0) { target = 0; } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "seek to position %d\n", target); switch_core_file_seek(fhp, &pos, target, SEEK_SET); } else { samps = atoi(p) * (codec->implementation->samples_per_second / 1000); if (samps < 0) { samps = 0; } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "seek to position %d\n", samps); switch_core_file_seek(fhp, &pos, samps, SEEK_SET); } } return SWITCH_STATUS_SUCCESS; } } if (!strcmp(result, "true") || !strcmp(result, "undefined")) { return SWITCH_STATUS_SUCCESS; } return SWITCH_STATUS_FALSE; }