]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-7505: clean up and support multiple formats to same extensions {modname=mod_vlc...
authorAnthony Minessale <anthm@freeswitch.org>
Wed, 18 Mar 2015 22:58:23 +0000 (17:58 -0500)
committerMichael Jerris <mike@jerris.com>
Thu, 28 May 2015 17:47:13 +0000 (12:47 -0500)
src/include/switch_loadable_module.h
src/include/switch_module_interfaces.h
src/include/switch_utils.h
src/mod/applications/mod_conference/mod_conference.c
src/mod/formats/mod_avformat/mod_avformat.c
src/mod/formats/mod_vlc/mod_vlc.c
src/switch_core_file.c
src/switch_ivr_play_say.c
src/switch_loadable_module.c

index 89549241f78b057fac654cceaa49403522ea4d32..f0ae57901c27c5c11d13af2347392abcabdc1cbd 100644 (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
index e1199ca9909967f71f8d4d8a0c4ff14cb274650d..49328503c01b8f038c464db1c17b59e4692bf908 100644 (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 */
index 3178d37f4d8517170e7599408ddc3b0436db7207..b34c09d7901e4d3be324c57afa883fa26658ee10 100644 (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 == '{') {
-                       e = switch_find_end_paren(file, '{', '}');
-               } else {
-                       break;
-               }
+       while (*file == '{') {
+               e = switch_find_end_paren(file, '{', '}');
+               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 == '{') {
-                       if ((e = switch_find_end_paren(file, '{', '}'))) {
-                               file = e + 1;
-                       }
-               } else {
-                       break;
+       while(*file == '{') {
+               if ((e = switch_find_end_paren(file, '{', '}'))) {
+                       file = e + 1;
+                       while(*file == ' ') file++;
                }
        }
 
index 860977d08e75b50a805e028d2d12216d4fe1cf4d..4fa8a57121509b0ca760a5e19491fd193c103b32 100644 (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,
index 57eeebc93c1a0b2ada8e42ba72fe44882edaa4b4..5c65df1d528ead579b7879864f1046dc5ac121e5 100644 (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];
index af2d8d940349a736d5d9a1dc713224907fac458b..3edfcdd29fa1bc99fcc3032d2c8d488cbc9c1547 100644 (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;
        }
+
+       ret = switch_vasprintf(&ldata, fmt, args);
+
+       if (ret == -1) return;
        
-       switch_log_printf(SWITCH_CHANNEL_LOG, fslevel, "%s\n", ldata);
+       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);
 
                }
        }
index ca29b03bf2d63179bb2b9d91ae0a9f18a0534d56..356a96669c3ad9e4daf3e2b2e182161a90185ba7 100644 (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) {
-                       if ((timeout = switch_event_get_header(fh->params, "timeout"))) {
-                               if ((to = atoi(timeout)) < 1) {
-                                       to = 0;
-                               }
+               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;
+                       }
+               }
+
+               if ((modname = switch_event_get_header(fh->params, "modname"))) {
+                       fh->modname = switch_core_strdup(fh->memory_pool, modname);
+               }
+
+               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;
                        }
-               } else {
-                       new_fp = fp;
                }
 
-               file_path = new_fp;
+               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);
        }
index 5ceeab3a289de1fd02a5d92b447b5decb0ea7d9a..8ca3769a797909662a8897217018f61c40bdf2a2 100644 (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, '[', ']'))) {
-                                       *e = '\0';
-                                       file = e + 1;
-                               } else {
-                                       tfile = NULL;
+                               
+                               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 == '[') {
-                                               tfile = switch_core_session_strdup(session, file);
-                                               if ((e = switch_find_end_paren(tfile, '[', ']'))) {
+                               if (*file == '{') {
+                                       tfile = switch_core_session_strdup(session, file);
+
+                                       while (*file == '{') {
+                                               if ((e = switch_find_end_paren(tfile, '{', '}'))) {
                                                        *e = '\0';
                                                        file = e + 1;
+                                                       while(*file == ' ') file++;
                                                } else {
                                                        tfile = NULL;
+                                                       break;
                                                }
-                                       } 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++;
index c9ec5f0e81aec5ec7473a2cf997fe9cb51eee6ba..de9a42d81b65853f71dda3d895e913494f5e0808 100644 (file)
 /* 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,10 +1149,30 @@ 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++;
                                        }
-                                       switch_core_hash_delete(loadable_modules.file_hash, ptr->extens[i]);
+
+                                       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)