FS-7505: clean up and support multiple formats to same extensions {modname=mod_vlc}rtmp://foo.com/flvplayback also move [/tmp]file to be {spool_path=/tmp}

This commit is contained in:
Anthony Minessale 2015-03-18 17:58:23 -05:00 committed by Michael Jerris
parent 13e60c420d
commit 52d15f6398
9 changed files with 292 additions and 173 deletions

View File

@ -203,7 +203,7 @@ SWITCH_DECLARE(switch_json_api_interface_t *) switch_loadable_module_get_json_ap
\param name the name of the file format
\return the desired file format interface
*/
SWITCH_DECLARE(switch_file_interface_t *) switch_loadable_module_get_file_interface(const char *name);
SWITCH_DECLARE(switch_file_interface_t *) switch_loadable_module_get_file_interface(const char *name, const char *modname);
/*!
\brief Retrieve the speech interface by it's registered name

View File

@ -298,6 +298,17 @@ struct switch_file_interface {
struct switch_file_interface *next;
};
typedef struct switch_mm_s {
int samplerate;
int channels;
int keyint;
int ab;
int vb;
int vw;
int vh;
float fps;
} switch_mm_t;
/*! an abstract representation of a file handle (some parameters based on compat with libsndfile) */
struct switch_file_handle {
/*! the interface of the module that implemented the current file type */
@ -360,6 +371,8 @@ struct switch_file_handle {
uint32_t cur_channels;
uint32_t cur_samplerate;
char *stream_name;
char *modname;
switch_mm_t mm;
};
/*! \brief Abstract interface to an asr module */

View File

@ -1032,7 +1032,6 @@ SWITCH_DECLARE(char *) switch_find_end_paren(const char *s, char open, char clos
static inline void switch_separate_file_params(const char *file, char **file_portion, char **params_portion)
{
char *e = NULL;
int x;
char *space = strdup(file);
file = space;
@ -1040,18 +1039,14 @@ static inline void switch_separate_file_params(const char *file, char **file_por
*file_portion = NULL;
*params_portion = NULL;
for (x = 0; x < 2; x++) {
if (*file == '[' && *(file + 1) == *SWITCH_PATH_SEPARATOR) {
e = switch_find_end_paren(file, '[', ']');
} else if (*file == '{') {
while (*file == '{') {
e = switch_find_end_paren(file, '{', '}');
} else {
break;
}
file = e + 1;
while(*file == ' ') file++;
}
if (e) {
file = e + 1;
*file_portion = strdup((char *)file);
*++e = '\0';
*params_portion = (char *)space;
@ -1065,19 +1060,12 @@ static inline void switch_separate_file_params(const char *file, char **file_por
static inline switch_bool_t switch_is_file_path(const char *file)
{
const char *e;
int r, x;
int r;
for (x = 0; x < 2; x++) {
if (*file == '[' && *(file + 1) == *SWITCH_PATH_SEPARATOR) {
if ((e = switch_find_end_paren(file, '[', ']'))) {
file = e + 1;
}
} else if (*file == '{') {
while(*file == '{') {
if ((e = switch_find_end_paren(file, '{', '}'))) {
file = e + 1;
}
} else {
break;
while(*file == ' ') file++;
}
}

View File

@ -6697,7 +6697,7 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th
if (conference->members_with_video && switch_test_flag(conference, CFLAG_TRANSCODE_VIDEO)) {
flags |= SWITCH_FILE_FLAG_VIDEO;
if (*rec->path != '{' && conference->canvas) {
if (conference->canvas) {
char *orig_path = rec->path;
rec->path = switch_core_sprintf(rec->pool, "{channels=%d,samplerate=%d,vw=%d,vh=%d,fps=%0.2f}%s",
conference->channels,

View File

@ -171,7 +171,7 @@ static int write_frame(AVFormatContext *fmt_ctx, const AVRational *time_base, AV
}
/* Add an output stream. */
static switch_status_t add_stream(OutputStream *ost, AVFormatContext *oc, AVCodec **codec, enum AVCodecID codec_id)
static switch_status_t add_stream(OutputStream *ost, AVFormatContext *oc, AVCodec **codec, enum AVCodecID codec_id, switch_mm_t *mm)
{
AVCodecContext *c;
switch_status_t status = SWITCH_STATUS_FALSE;
@ -203,11 +203,21 @@ static switch_status_t add_stream(OutputStream *ost, AVFormatContext *oc, AVCode
c->sample_rate = ost->sample_rate = 44100;
c->channels = ost->channels;
c->channel_layout = av_get_default_channel_layout(c->channels);
if (mm) {
if (mm->ab) {
c->bit_rate = mm->ab * 1024;
}
if (mm->samplerate) {
c->sample_rate = ost->sample_rate = mm->samplerate;
}
}
break;
case AVMEDIA_TYPE_VIDEO:
c->codec_id = codec_id;
c->bit_rate = 450000;
c->bit_rate = 1000000;
/* Resolution must be a multiple of two. */
c->width = ost->width;
c->height = ost->height;
@ -220,6 +230,16 @@ static switch_status_t add_stream(OutputStream *ost, AVFormatContext *oc, AVCode
if (codec_id == AV_CODEC_ID_VP8) {
av_set_options_string(c, "quality=realtime", "=", ":");
}
if (mm) {
if (mm->vb) {
c->bit_rate = mm->vb * 1000;
}
if (mm->keyint) {
c->gop_size = mm->keyint;
}
}
break;
default:
break;
@ -307,8 +327,8 @@ static switch_status_t open_audio(AVFormatContext *oc, AVCodec *codec, OutputStr
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "sample_rate: %d nb_samples: %d\n", ost->frame->sample_rate, ost->frame->nb_samples);
// disable resampler for now before we figure out the correct params
if (0 && c->sample_fmt != AV_SAMPLE_FMT_S16) {
if (c->sample_fmt != AV_SAMPLE_FMT_S16) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "sample_fmt %d != AV_SAMPLE_FMT_S16, start resampler\n", c->sample_fmt);
ost->resample_ctx = avresample_alloc_context();
@ -402,7 +422,7 @@ static void *SWITCH_THREAD_FUNC video_thread_run(switch_thread_t *thread, void *
continue;
}
switch_mutex_lock(eh->mutex);
//switch_mutex_lock(eh->mutex);
eh->in_callback = 1;
@ -435,12 +455,14 @@ static void *SWITCH_THREAD_FUNC video_thread_run(switch_thread_t *thread, void *
}
if (got_packet) {
switch_mutex_lock(eh->mutex);
ret = write_frame(eh->oc, &eh->video_st->st->codec->time_base, eh->video_st->st, &pkt);
switch_mutex_unlock(eh->mutex);
av_free_packet(&pkt);
}
eh->in_callback = 0;
switch_mutex_unlock(eh->mutex);
//switch_mutex_unlock(eh->mutex);
}
switch_img_free(&last_img);
@ -586,7 +608,7 @@ SWITCH_STANDARD_APP(record_av_function)
video_st.width = vid_params.width;
video_st.height = vid_params.height;
video_st.next_pts = switch_time_now() / 1000;
if (add_stream(&video_st, oc, &video_codec, fmt->video_codec) == SWITCH_STATUS_SUCCESS &&
if (add_stream(&video_st, oc, &video_codec, fmt->video_codec, NULL) == SWITCH_STATUS_SUCCESS &&
open_video(oc, video_codec, &video_st) == SWITCH_STATUS_SUCCESS) {
avcodec_string(codec_str, sizeof(codec_str), video_st.st->codec, 1);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "use video codec implementation %s\n", codec_str);
@ -598,7 +620,7 @@ SWITCH_STANDARD_APP(record_av_function)
audio_st.channels = read_impl.number_of_channels;
audio_st.sample_rate = force_sample_rate;
add_stream(&audio_st, oc, &audio_codec, fmt->audio_codec);
add_stream(&audio_st, oc, &audio_codec, fmt->audio_codec, NULL);
if (open_audio(oc, audio_codec, &audio_st) != SWITCH_STATUS_SUCCESS) {
goto end;
}
@ -1037,7 +1059,8 @@ static void log_callback(void *ptr, int level, const char *fmt, va_list vl)
{
switch_log_level_t switch_level = SWITCH_LOG_DEBUG;
if (level > AV_LOG_INFO) return;
/* naggy messages */
if (level == AV_LOG_DEBUG || level == AV_LOG_WARNING) return;
switch(level) {
case AV_LOG_QUIET: switch_level = SWITCH_LOG_CONSOLE; break;
@ -1112,7 +1135,7 @@ static switch_status_t av_file_open(switch_file_handle_t *handle, const char *pa
memset(context, 0, sizeof(av_file_context_t));
context->offset = 0; // 1200 ?
context->offset = 1200;
if (handle->params && (tmp = switch_event_get_header(handle->params, "av_video_offset"))) {
context->offset = atoi(tmp);
}
@ -1170,6 +1193,38 @@ static switch_status_t av_file_open(switch_file_handle_t *handle, const char *pa
if (fmt->audio_codec != AV_CODEC_ID_AAC) {
fmt->audio_codec = AV_CODEC_ID_AAC; // force AAC
}
handle->mm.samplerate = 44100;
handle->mm.ab = 128;
if (handle->mm.vw && handle->mm.vh) {
switch(handle->mm.vh) {
case 240:
handle->mm.vb = 400;
break;
case 360:
handle->mm.vb = 750;
break;
case 480:
handle->mm.vb = 1000;
break;
case 720:
handle->mm.vb = 2500;
break;
case 1080:
handle->mm.vb = 4500;
break;
default:
handle->mm.vb = (handle->mm.vw * handle->mm.vh) / 175;
break;
}
}
if (handle->mm.fps > 0.0f) {
handle->mm.keyint = (int) 2.0f * handle->mm.fps;
}
}
desc = avcodec_descriptor_get(fmt->video_codec);
@ -1181,7 +1236,7 @@ static switch_status_t av_file_open(switch_file_handle_t *handle, const char *pa
context->audio_st.channels = handle->channels;
context->audio_st.sample_rate = handle->samplerate;
add_stream(&context->audio_st, context->oc, &context->audio_codec, fmt->audio_codec);
add_stream(&context->audio_st, context->oc, &context->audio_codec, fmt->audio_codec, &handle->mm);
if (open_audio(context->oc, context->audio_codec, &context->audio_st) != SWITCH_STATUS_SUCCESS) {
goto end;
}
@ -1292,22 +1347,22 @@ static switch_status_t av_file_write(switch_file_handle_t *handle, void *data, s
context->offset = 0;
}
if (context->mutex) switch_mutex_lock(context->mutex);
switch_buffer_write(context->audio_buffer, data, datalen);
bytes = context->audio_st.frame->nb_samples * 2 * context->audio_st.st->codec->channels;
inuse = switch_buffer_inuse(context->audio_buffer);
while (inuse >= bytes) {
//inuse = switch_buffer_inuse(context->audio_buffer);
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "inuse: %d samples: %d bytes: %d\n", inuse, context->audio_st.frame->nb_samples, bytes);
while ((inuse = switch_buffer_inuse(context->audio_buffer)) >= bytes) {
AVPacket pkt = { 0 };
int got_packet = 0;
int ret;
av_init_packet(&pkt);
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "inuse: %d samples: %d bytes: %d\n", inuse, audio_st.frame->nb_samples, bytes);
if (0 && context->audio_st.resample_ctx) { // need resample
if (context->audio_st.resample_ctx) { // need resample
int out_samples = avresample_get_out_samples(context->audio_st.resample_ctx, context->audio_st.frame->nb_samples);
av_frame_make_writable(context->audio_st.frame);
@ -1321,7 +1376,6 @@ static switch_status_t av_file_write(switch_file_handle_t *handle, void *data, s
if (ret < 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error while converting %d samples, error text: %s\n",
context->audio_st.frame->nb_samples, get_error_text(ret));
inuse = switch_buffer_inuse(context->audio_buffer);
continue;
}
@ -1340,22 +1394,21 @@ static switch_status_t av_file_write(switch_file_handle_t *handle, void *data, s
if (ret < 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Error encoding audio frame: %d\n", ret);
inuse = switch_buffer_inuse(context->audio_buffer);
continue;
}
if (got_packet) {
if (context->mutex) switch_mutex_lock(context->mutex);
ret = write_frame(context->oc, &context->audio_st.st->codec->time_base, context->audio_st.st, &pkt);
if (context->mutex) switch_mutex_unlock(context->mutex);
if (ret < 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error while writing audio frame: %s\n", get_error_text(ret));
switch_goto_status(SWITCH_STATUS_FALSE, end);
}
}
inuse = switch_buffer_inuse(context->audio_buffer);
}
if (context->mutex) switch_mutex_unlock(context->mutex);
end:
return status;
@ -1379,7 +1432,7 @@ static switch_status_t av_file_write_video(switch_file_handle_t *handle, switch_
context->video_st.width = frame->img->d_w;
context->video_st.height = frame->img->d_h;
context->video_st.next_pts = switch_time_now() / 1000;
if (add_stream(&context->video_st, context->oc, &context->video_codec, context->oc->oformat->video_codec) == SWITCH_STATUS_SUCCESS &&
if (add_stream(&context->video_st, context->oc, &context->video_codec, context->oc->oformat->video_codec, &handle->mm) == SWITCH_STATUS_SUCCESS &&
open_video(context->oc, context->video_codec, &context->video_st) == SWITCH_STATUS_SUCCESS) {
char codec_str[256];

View File

@ -62,7 +62,7 @@ typedef int (*imem_get_t)(void *data, const char *cookie,
typedef void (*imem_release_t)(void *data, const char *cookie, size_t, void *);
/* Change value to -vvv for vlc related debug. Be careful since vlc is at least as verbose as FS about logging */
const char *vlc_args[] = {"-vvvv"};
const char *vlc_args[] = {"-v"};
//const char *vlc_args[] = {"--network-caching=0"};
//--sout-mux-caching
@ -158,9 +158,10 @@ void log_cb(void *data, int level, const libvlc_log_t *ctx, const char *fmt, va_
switch_log_level_t fslevel = SWITCH_LOG_DEBUG;
int ret;
ret = switch_vasprintf(&ldata, fmt, args);
if (ret == -1) return;
/* vlc abuses logging too much these leves spew nonsense (comment to do deep testing) */
if (level == LIBVLC_DEBUG || level == LIBVLC_WARNING) {
return;
}
switch(level) {
case LIBVLC_NOTICE:
@ -174,11 +175,19 @@ void log_cb(void *data, int level, const libvlc_log_t *ctx, const char *fmt, va_
break;
case LIBVLC_DEBUG:
default:
fslevel = SWITCH_LOG_DEBUG;
fslevel = SWITCH_LOG_DEBUG1;
break;
}
switch_log_printf(SWITCH_CHANNEL_LOG, fslevel, "%s\n", ldata);
ret = switch_vasprintf(&ldata, fmt, args);
if (ret == -1) return;
if (end_of(ldata) == '\n') {
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, fslevel, "VLC: %s", ldata);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, fslevel, "VLC: %s\n", ldata);
}
switch_safe_free(ldata);
}
@ -753,17 +762,8 @@ static switch_status_t vlc_file_open(switch_file_handle_t *handle, const char *p
char *ext = NULL;
switch_file_t *fd = NULL;
const char *realpath = NULL;
float fps = 0.0f;
int is_stream = 0;
int samplerate = 44100;
int channels = 1;
int keyint = 60;
int ab = 0;
int vb = 0;
int vw = 0;
int vh = 0;
int tmp;
const char *val;
context = switch_core_alloc(handle->memory_pool, sizeof(*context));
context->pool = handle->memory_pool;
@ -772,50 +772,6 @@ static switch_status_t vlc_file_open(switch_file_handle_t *handle, const char *p
realpath = path;
if (handle->params) {
if ((val = switch_event_get_header(handle->params, "samplerate"))) {
tmp = atoi(val);
if (tmp > 8000) {
samplerate = tmp;
}
}
if ((val = switch_event_get_header(handle->params, "channels"))) {
tmp = atoi(val);
if (tmp == 1 || tmp == 2) {
channels = tmp;
}
}
if ((val = switch_event_get_header(handle->params, "ab"))) {
tmp = atoi(val);
if (tmp > 16) {
ab = tmp;
}
}
if ((val = switch_event_get_header(handle->params, "vw"))) {
tmp = atoi(val);
if (tmp > 0) {
vw = tmp;
}
}
if ((val = switch_event_get_header(handle->params, "vh"))) {
tmp = atoi(val);
if (tmp > 0) {
vh = tmp;
}
}
if ((val = switch_event_get_header(handle->params, "fps"))) {
float ftmp = atof(val);
if (ftmp > 0.0f) {
fps = ftmp;
}
}
}
if (switch_test_flag(handle, SWITCH_FILE_FLAG_VIDEO) && switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
if ((ext = strrchr(path, '.')) && !strcasecmp(ext, ".mp4")) {
@ -823,34 +779,34 @@ static switch_status_t vlc_file_open(switch_file_handle_t *handle, const char *p
path = switch_core_sprintf(context->pool, "#transcode{vcodec=h264,acodec=mp3}:std{access=file,mux=mp4,dst=%s}", path);
} else if (handle->stream_name && (!strcasecmp(handle->stream_name, "rtmp") || !strcasecmp(handle->stream_name, "youtube"))) {
samplerate = 44100;
ab = 128;
handle->mm.samplerate = 44100;
handle->mm.ab = 128;
if (vw && vh) {
switch(vh) {
if (handle->mm.vw && handle->mm.vh) {
switch(handle->mm.vh) {
case 240:
vb = 400;
handle->mm.vb = 400;
break;
case 360:
vb = 750;
handle->mm.vb = 750;
break;
case 480:
vb = 1000;
handle->mm.vb = 1000;
break;
case 720:
vb = 2500;
handle->mm.vb = 2500;
break;
case 1080:
vb = 4500;
handle->mm.vb = 4500;
break;
default:
vb = (vw * vh) / 175;
handle->mm.vb = (handle->mm.vw * handle->mm.vh) / 175;
break;
}
}
if (fps > 0.0f) {
keyint = (int) 2.0f * fps;
if (handle->mm.fps > 0.0f) {
handle->mm.keyint = (int) 2.0f * handle->mm.fps;
}
path = switch_core_sprintf(context->pool,
@ -868,7 +824,7 @@ static switch_status_t vlc_file_open(switch_file_handle_t *handle, const char *p
"mux=flv,"
"dst=rtmp://%s"
"}",
keyint, ab, vb, channels, samplerate, path);
handle->mm.keyint, handle->mm.ab, handle->mm.vb, handle->mm.channels, handle->mm.samplerate, path);
}
}

View File

@ -80,22 +80,83 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_file_open(const char *file,
switch_set_flag(fh, SWITCH_FILE_FLAG_FREE_POOL);
}
fh->mm.samplerate = 44100;
fh->mm.channels = 1;
fh->mm.keyint = 60;
fh->mm.ab = 128;
if (*file_path == '{') {
char *timeout;
char *new_fp;
char *modname;
const char *val;
int tmp;
fp = switch_core_strdup(fh->memory_pool, file_path);
if (switch_event_create_brackets(fp, '{', '}', ',', &fh->params, &new_fp, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
while (*fp == '{') {
char *parsed = NULL;
if (switch_event_create_brackets(fp, '{', '}', ',', &fh->params, &parsed, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS || !parsed) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
goto fail;
}
fp = parsed;
}
file_path = fp;
if ((timeout = switch_event_get_header(fh->params, "timeout"))) {
if ((to = atoi(timeout)) < 1) {
to = 0;
}
}
} else {
new_fp = fp;
if ((modname = switch_event_get_header(fh->params, "modname"))) {
fh->modname = switch_core_strdup(fh->memory_pool, modname);
}
file_path = new_fp;
if ((val = switch_event_get_header(fh->params, "samplerate"))) {
tmp = atoi(val);
if (tmp > 8000) {
fh->mm.samplerate = tmp;
}
}
if ((val = switch_event_get_header(fh->params, "channels"))) {
tmp = atoi(val);
if (tmp == 1 || tmp == 2) {
fh->mm.channels = tmp;
}
}
if ((val = switch_event_get_header(fh->params, "ab"))) {
tmp = atoi(val);
if (tmp > 16) {
fh->mm.ab = tmp;
}
}
if ((val = switch_event_get_header(fh->params, "vw"))) {
tmp = atoi(val);
if (tmp > 0) {
fh->mm.vw = tmp;
}
}
if ((val = switch_event_get_header(fh->params, "vh"))) {
tmp = atoi(val);
if (tmp > 0) {
fh->mm.vh = tmp;
}
}
if ((val = switch_event_get_header(fh->params, "fps"))) {
float ftmp = atof(val);
if (ftmp > 0.0f) {
fh->mm.fps = ftmp;
}
}
}
if (switch_directory_exists(file_path, fh->memory_pool) == SWITCH_STATUS_SUCCESS) {
@ -114,26 +175,13 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_file_open(const char *file,
} else {
if ((flags & SWITCH_FILE_FLAG_WRITE)) {
char *p, *e;
fh->file_path = switch_core_strdup(fh->memory_pool, file_path);
p = fh->file_path;
if (*p == '[' && *(p + 1) == *SWITCH_PATH_SEPARATOR) {
e = switch_find_end_paren(p, '[', ']');
if (e) {
*e = '\0';
spool_path = p + 1;
fh->file_path = e + 1;
}
if (fh->params) {
spool_path = switch_event_get_header(fh->params, "spool_path");
}
if (!spool_path) {
spool_path = switch_core_get_variable_pdup(SWITCH_AUDIO_SPOOL_PATH_VARIABLE, fh->memory_pool);
}
file_path = fh->file_path;
}
if ((ext = strrchr(file_path, '.')) == 0) {
@ -146,7 +194,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_file_open(const char *file,
if ((fh->file_interface = switch_loadable_module_get_file_interface(ext)) == 0) {
if ((fh->file_interface = switch_loadable_module_get_file_interface(ext, fh->modname)) == 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid file format [%s] for [%s]!\n", ext, file_path);
switch_goto_status(SWITCH_STATUS_GENERR, fail);
}

View File

@ -477,17 +477,22 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
char *tfile = NULL;
char *e;
if (*file == '[') {
if (*file == '{') {
tfile = switch_core_session_strdup(session, file);
if ((e = switch_find_end_paren(tfile, '[', ']'))) {
while (*file == '{') {
if ((e = switch_find_end_paren(tfile, '{', '}'))) {
*e = '\0';
file = e + 1;
while(*file == ' ') file++;
} else {
tfile = NULL;
break;
}
}
}
file = switch_core_session_sprintf(session, "%s%s%s%s%s", switch_str_nil(tfile), tfile ? "]" : "", prefix, SWITCH_PATH_SEPARATOR, file);
file = switch_core_session_sprintf(session, "%s%s%s%s%s", switch_str_nil(tfile), tfile ? "}" : "", prefix, SWITCH_PATH_SEPARATOR, file);
}
if ((ext = strrchr(file, '.'))) {
ext++;
@ -1210,33 +1215,25 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
if (!strstr(file, SWITCH_URL_SEPARATOR)) {
if (!switch_is_file_path(file)) {
char *tfile = NULL, *tfile2 = NULL;
char *tfile = NULL;
char *e;
int x;
for (x = 0; x < 2; x++) {
if (*file == '[') {
if (*file == '{') {
tfile = switch_core_session_strdup(session, file);
if ((e = switch_find_end_paren(tfile, '[', ']'))) {
while (*file == '{') {
if ((e = switch_find_end_paren(tfile, '{', '}'))) {
*e = '\0';
file = e + 1;
while(*file == ' ') file++;
} else {
tfile = NULL;
}
} else if (*file == '{') {
tfile2 = switch_core_session_strdup(session, file);
if ((e = switch_find_end_paren(tfile2, '{', '}'))) {
*e = '\0';
file = e + 1;
} else {
tfile2 = NULL;
}
} else {
break;
}
}
}
file = switch_core_session_sprintf(session, "%s%s%s%s%s%s%s", switch_str_nil(tfile), tfile ? "]" : "", switch_str_nil(tfile2), tfile2 ? "}" : "", prefix, SWITCH_PATH_SEPARATOR, file);
file = switch_core_session_sprintf(session, "%s%s%s%s%s", switch_str_nil(tfile), tfile ? "}" : "", prefix, SWITCH_PATH_SEPARATOR, file);
}
if ((ext = strrchr(file, '.'))) {
ext++;

View File

@ -41,6 +41,13 @@
/* for apr file and directory handling */
#include <apr_file_io.h>
typedef struct switch_file_node_s {
const switch_file_interface_t *ptr;
const char *interface_name;
struct switch_file_node_s *next;
} switch_file_node_t;
struct switch_loadable_module {
char *key;
char *filename;
@ -361,6 +368,8 @@ static switch_status_t switch_loadable_module_process(char *key, switch_loadable
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to load file interface from %s due to no file extensions.\n", key);
} else {
int i;
switch_file_node_t *node, *head;
for (i = 0; ptr->extens[i]; i++) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding File Format '%s'\n", ptr->extens[i]);
if (switch_event_create(&event, SWITCH_EVENT_MODULE_LOAD) == SWITCH_STATUS_SUCCESS) {
@ -368,10 +377,18 @@ static switch_status_t switch_loadable_module_process(char *key, switch_loadable
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->extens[i]);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "module", new_module->module_interface->module_name);
switch_event_fire(&event);
added++;
}
switch_core_hash_insert(loadable_modules.file_hash, ptr->extens[i], (const void *) ptr);
node = switch_core_alloc(new_module->pool, sizeof(*node));
node->ptr = ptr;
node->interface_name = switch_core_strdup(new_module->pool, new_module->module_interface->module_name);
if ((head = switch_core_hash_find(loadable_modules.file_hash, ptr->extens[i]))) {
node->next = head;
}
switch_core_hash_insert(loadable_modules.file_hash, ptr->extens[i], (const void *) node);
}
}
}
@ -1112,6 +1129,7 @@ static switch_status_t switch_loadable_module_unprocess(switch_loadable_module_t
if (old_module->module_interface->file_interface) {
const switch_file_interface_t *ptr;
switch_file_node_t *node, *head, *last = NULL;
for (ptr = old_module->module_interface->file_interface; ptr; ptr = ptr->next) {
if (ptr->interface_name) {
@ -1131,11 +1149,31 @@ static switch_status_t switch_loadable_module_unprocess(switch_loadable_module_t
if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "file");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->extens[i]);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "module", old_module->module_interface->module_name);
switch_event_fire(&event);
removed++;
}
if ((head = switch_core_hash_find(loadable_modules.file_hash, ptr->extens[i]))) {
for(node = head; node; node = node->next) {
if (!strcmp(node->interface_name, old_module->module_interface->module_name)) {
if (node == head) {
if ((node = node->next)) {
switch_core_hash_insert(loadable_modules.file_hash, ptr->extens[i], (const void *) node);
} else {
switch_core_hash_delete(loadable_modules.file_hash, ptr->extens[i]);
}
} else {
if (last) {
last->next = node->next;
}
}
break;
}
last = node;
}
}
}
}
}
}
@ -2041,6 +2079,33 @@ SWITCH_DECLARE(switch_endpoint_interface_t *) switch_loadable_module_get_endpoin
return ptr;
}
SWITCH_DECLARE(switch_file_interface_t *) switch_loadable_module_get_file_interface(const char *name, const char *modname)
{
switch_file_interface_t *i = NULL;
switch_file_node_t *node, *head;
switch_mutex_lock(loadable_modules.mutex);
if ((head = switch_core_hash_find(loadable_modules.file_hash, name))) {
if (modname) {
for (node = head; node; node = node->next) {
if (!strcasecmp(node->interface_name, modname)) {
i = (switch_file_interface_t *) node->ptr;
break;
}
}
} else {
i = (switch_file_interface_t *) head->ptr;
}
}
switch_mutex_unlock(loadable_modules.mutex);
if (i) PROTECT_INTERFACE(i);
return i;
}
SWITCH_DECLARE(switch_codec_interface_t *) switch_loadable_module_get_codec_interface(const char *name)
{
char altname[256] = "";
@ -2083,7 +2148,6 @@ HASH_FUNC(application)
HASH_FUNC(chat_application)
HASH_FUNC(api)
HASH_FUNC(json_api)
HASH_FUNC(file)
HASH_FUNC(speech)
HASH_FUNC(asr)
HASH_FUNC(directory)