]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
make test 'record' app in app_playback.c
authorAnthony Minessale <anthony.minessale@gmail.com>
Fri, 27 Jan 2006 01:46:14 +0000 (01:46 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Fri, 27 Jan 2006 01:46:14 +0000 (01:46 +0000)
You are best off doing wav (trust me)
It can record at 8 16 22 and 32 khz if you can manage to have a channel at that speed.

syntax [record /tmp/blah.wav]

dial * to end (dtmf only works in iax and portaudio {beg file to add it to mod_exosip})

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@453 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/include/switch_core.h
src/include/switch_ivr.h
src/mod/applications/mod_playback/mod_playback.c
src/mod/formats/mod_sndfile/mod_sndfile.c
src/switch_core.c
src/switch_ivr.c

index 1221e3ff2c425602311ab209d071c984674a26a2..a9562b28b121fe7577dec86ff626c47df4da7719 100644 (file)
@@ -641,6 +641,13 @@ SWITCH_DECLARE(switch_status) switch_core_codec_destroy(switch_codec *codec);
 */
 SWITCH_DECLARE(switch_status) switch_core_session_set_read_codec(switch_core_session *session, switch_codec *codec);
 
+/*! 
+  \brief Retrieve the read codec from a given session
+  \param session session to retrieve from
+  \return a pointer to the codec
+*/
+SWITCH_DECLARE(switch_codec *) switch_core_session_get_read_codec(switch_core_session *session);
+
 /*! 
   \brief Assign the write codec to a given session
   \param session session to add the codec to
@@ -648,8 +655,15 @@ SWITCH_DECLARE(switch_status) switch_core_session_set_read_codec(switch_core_ses
   \return SWITCH_STATUS_SUCCESS if successful
 */
 SWITCH_DECLARE(switch_status) switch_core_session_set_write_codec(switch_core_session *session, switch_codec *codec);
-///\}
 
+/*! 
+  \brief Retrieve the write codec from a given session
+  \param session session to retrieve from
+  \return a pointer to the codec
+*/
+SWITCH_DECLARE(switch_codec *) switch_core_session_get_write_codec(switch_core_session *session);
+
+///\}
 ///\defgroup db Database Functions
 ///\ingroup core1
 ///\{
@@ -684,7 +698,7 @@ SWITCH_DECLARE(switch_status) switch_core_file_open(switch_file_handle *fh, char
 
 /*! 
   \brief Read media from a file handle
-  \param fh the file handle to read from
+  \param fh the file handle to read from (must be initilized by you memset all 0 for read, fill in channels and rate for write)
   \param data the buffer to read the data to
   \param len the max size of the buffer
   \return SWITCH_STATUS_SUCCESS with len adjusted to the bytes read if successful
index 890360f34d54331009b6b5a6c7eae3d135f11458..0f0209e09099fb7f81c2ae2e4b35601de45ca769 100644 (file)
@@ -64,6 +64,19 @@ SWITCH_DECLARE(switch_status) switch_ivr_play_file(switch_core_session *session,
                                                                                                   char *file,
                                                                                                   char *timer_name,
                                                                                                   switch_dtmf_callback_function dtmf_callback);
+
+
+
+/*!
+  \brief record a file from the session to a file
+  \param session the session to record from
+  \param file the path to the file
+  \param dtmf_callback code to execute if any dtmf is dialed during the recording
+  \return SWITCH_STATUS_SUCCESS if all is well
+*/
+SWITCH_DECLARE(switch_status) switch_ivr_record_file(switch_core_session *session,
+                                                                                                        char *file,
+                                                                                                        switch_dtmf_callback_function dtmf_callback);
        
 /** @} */
 
index b1aafcc4c4ece9f6714dca391b0c4812de8a4edc..9f06cb52d4f81f0d2cf24f9864e608352bfefab6 100644 (file)
@@ -73,9 +73,29 @@ void playback_function(switch_core_session *session, char *data)
        
 }
 
+
+void record_function(switch_core_session *session, char *data)
+{
+       switch_channel *channel;
+       channel = switch_core_session_get_channel(session);
+    assert(channel != NULL);
+
+       if (switch_ivr_record_file(session, data, on_dtmf) != SWITCH_STATUS_SUCCESS) {
+               switch_channel_hangup(channel);
+       }
+       
+}
+
+static const switch_application_interface record_application_interface = {
+       /*.interface_name */ "record",
+       /*.application_function */ record_function
+};
+
 static const switch_application_interface playback_application_interface = {
        /*.interface_name */ "playback",
-       /*.application_function */ playback_function
+       /*.application_function */ playback_function,
+       NULL,NULL,NULL,
+       /*.next*/                                 &record_application_interface
 };
 
 static const switch_loadable_module_interface mod_playback_module_interface = {
index c76e6b0d496f3ba8a812ac6746e3a73f64db51d1..99faee6285bf2e0729d6238db3cb29f8c14d0390 100644 (file)
@@ -46,7 +46,8 @@ switch_status sndfile_file_open(switch_file_handle *handle, char *path)
        sndfile_context *context;
        int mode = 0;
        char *ext;
-
+       int ready = 1;
+       
        if (!(ext = strrchr(path, '.'))) {
                switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Invalid Format\n");
                return SWITCH_STATUS_GENERR;
@@ -67,40 +68,60 @@ switch_status sndfile_file_open(switch_file_handle *handle, char *path)
                return SWITCH_STATUS_GENERR;
        }
 
-
        if (!(context = switch_core_alloc(handle->memory_pool, sizeof(*context)))) {
                return SWITCH_STATUS_MEMERR;
        }
 
-       if (!strcmp(ext, "r8") || !strcmp(ext, "raw")) {
-               context->sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_PCM_16;
-               context->sfinfo.channels = 1;
-               context->sfinfo.samplerate = 8000;
-       }
+       if (mode & SFM_WRITE) {
+               context->sfinfo.channels = handle->channels;
+               context->sfinfo.samplerate = handle->samplerate;
+               if (handle->samplerate == 8000 || handle->samplerate == 16000) {
+                       context->sfinfo.format |= SF_FORMAT_PCM_16;
+               } else if (handle->samplerate == 24000) {
+                       context->sfinfo.format |= SF_FORMAT_PCM_24;
+               } else if (handle->samplerate == 32000) {
+                       context->sfinfo.format |= SF_FORMAT_PCM_32;
+               }
 
-       if (!strcmp(ext, "r16")) {
-               context->sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_PCM_16;
-               context->sfinfo.channels = 1;
-               context->sfinfo.samplerate = 16000;
+               /* Could add more else if() but i am too lazy atm.. */
+               if (!strcasecmp(ext, "wav")) {
+                       context->sfinfo.format |= SF_FORMAT_WAV;
+               } else {
+                       ready = 0;
+               }
        }
 
-       if (!strcmp(ext, "r24")) {
-               context->sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_PCM_24;
-               context->sfinfo.channels = 1;
-               context->sfinfo.samplerate = 24000;
-       }
 
-       if (!strcmp(ext, "r32")) {
-               context->sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_PCM_32;
-               context->sfinfo.channels = 1;
-               context->sfinfo.samplerate = 32000;
+       if (!ready) {
+               if (!strcmp(ext, "r8") || !strcmp(ext, "raw")) {
+                       context->sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_PCM_16;
+                       context->sfinfo.channels = 1;
+                       context->sfinfo.samplerate = 8000;
+               } else if (!strcmp(ext, "r16")) {
+                       context->sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_PCM_16;
+                       context->sfinfo.channels = 1;
+                       context->sfinfo.samplerate = 16000;
+               } else if (!strcmp(ext, "r24")) {
+                       context->sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_PCM_24;
+                       context->sfinfo.channels = 1;
+                       context->sfinfo.samplerate = 24000;
+               } else if (!strcmp(ext, "r32")) {
+                       context->sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_PCM_32;
+                       context->sfinfo.channels = 1;
+                       context->sfinfo.samplerate = 32000;
+               } else if (!strcmp(ext, "gsm")) {
+                       context->sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_GSM610;
+                       context->sfinfo.channels = 1;
+                       context->sfinfo.samplerate = 8000;
+               }
        }
 
-       if (!strcmp(ext, "gsm")) {
-               context->sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_GSM610;
-               context->sfinfo.channels = 1;
-               context->sfinfo.samplerate = 8000;
-       }
+
+       if ((mode & SFM_WRITE) && sf_format_check (&context->sfinfo) == 0) {
+               switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Error : file format is invalid (0x%08X).\n", context->sfinfo.format);
+               return SWITCH_STATUS_GENERR;
+       };
+
 
        if (!(context->handle = sf_open(path, mode, &context->sfinfo))) {
                switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Error Opening File [%s] [%s]\n", path,
index 8f6b7e322c679c5f57142ed4af8a3d75ece8062e..294c54bdd682eb152d0f348a80f824a4d80cc35c 100644 (file)
@@ -212,6 +212,10 @@ SWITCH_DECLARE(switch_status) switch_core_session_set_read_codec(switch_core_ses
        return SWITCH_STATUS_SUCCESS;
 }
 
+SWITCH_DECLARE(switch_codec *) switch_core_session_get_read_codec(switch_core_session *session)
+{
+       return session->read_codec;
+}
 
 SWITCH_DECLARE(switch_status) switch_core_session_set_write_codec(switch_core_session *session, switch_codec *codec)
 {
@@ -221,6 +225,11 @@ SWITCH_DECLARE(switch_status) switch_core_session_set_write_codec(switch_core_se
        return SWITCH_STATUS_SUCCESS;
 }
 
+SWITCH_DECLARE(switch_codec *) switch_core_session_get_write_codec(switch_core_session *session)
+{
+       return session->write_codec;
+}
+
 SWITCH_DECLARE(switch_status) switch_core_codec_init(switch_codec *codec, char *codec_name, int rate, int ms,
                                                                                                         int channels, switch_codec_flag flags,
                                                                                                         const switch_codec_settings *codec_settings,
@@ -361,8 +370,6 @@ SWITCH_DECLARE(switch_status) switch_core_file_open(switch_file_handle *fh, char
        char *ext;
        switch_status status;
 
-       memset(fh, 0, sizeof(*fh));
-
        if (!(ext = strrchr(file_path, '.'))) {
                switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Invalid Format\n");
                return SWITCH_STATUS_FALSE;
index 566b4cec372ea9e9c102e24a69030c6538f77d6a..71dc8bbaa7e745291398403113c4391857074acf 100644 (file)
 #include <switch_ivr.h>
 
 
-/* TBD (Lots! there is only 1 function in here lol) */
+/* TBD (Lots! there are only 2 functions in here lol) */
+
+
+SWITCH_DECLARE(switch_status) switch_ivr_record_file(switch_core_session *session, 
+                                                                                                        char *file,
+                                                                                                        switch_dtmf_callback_function dtmf_callback)
+{
+       switch_channel *channel;
+    char dtmf[128];
+       switch_file_handle fh;
+       switch_frame *read_frame;
+       switch_codec codec, *read_codec;
+       char *codec_name;
+       switch_status status = SWITCH_STATUS_SUCCESS;
+       
+       memset(&fh, 0, sizeof(fh));
+
+       channel = switch_core_session_get_channel(session);
+    assert(channel != NULL);
+
+       read_codec = switch_core_session_get_read_codec(session);
+       assert(read_codec != NULL);
+
+       fh.channels = read_codec->implementation->number_of_channels;
+       fh.samplerate = read_codec->implementation->samples_per_second;
+
+
+       if (switch_core_file_open(&fh,
+                                                         file,
+                                                         SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT,
+                                                         switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
+               switch_channel_hangup(channel);
+               return SWITCH_STATUS_GENERR;
+       }
+
+       switch_channel_answer(channel);
+
+       
+       codec_name = "L16";
+       if (switch_core_codec_init(&codec,
+                                                          codec_name,
+                                                          read_codec->implementation->samples_per_second,
+                                                          read_codec->implementation->microseconds_per_frame / 1000,
+                                                          read_codec->implementation->number_of_channels,
+                                                          SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
+                                                          NULL, switch_core_session_get_pool(session)) == SWITCH_STATUS_SUCCESS) {
+               switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Raw Codec Activated\n");
+               switch_core_session_set_read_codec(session, &codec);            
+       } else {
+               switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Raw Codec Activation Failed %s@%dhz %d channels %dms\n",
+                                                         codec_name, fh.samplerate, fh.channels, read_codec->implementation->microseconds_per_frame / 1000);
+               switch_core_file_close(&fh);
+               return SWITCH_STATUS_GENERR;
+       }
+       
+
+       while (switch_channel_get_state(channel) == CS_EXECUTE) {
+               int len;
+
+               if (dtmf_callback) {
+                       /*
+                         dtmf handler function you can hook up to be executed when a digit is dialed during playback 
+                         if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
+                       */
+                       if (switch_channel_has_dtmf(channel)) {
+                               switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf));
+                               status = dtmf_callback(session, dtmf);
+                       }
+
+                       if (status != SWITCH_STATUS_SUCCESS) {
+                               break;
+                       }
+               }
+
+               if (switch_core_session_read_frame(session, &read_frame, -1, 0) != SWITCH_STATUS_SUCCESS) {
+                       break;
+               }
+
+               len = read_frame->datalen / 2;
+               switch_core_file_write(&fh, read_frame->data, &len);
+       }
+
+       switch_core_session_set_read_codec(session, read_codec);
+       switch_core_file_close(&fh);
+
+       return status;
+}
 
 SWITCH_DECLARE(switch_status) switch_ivr_play_file(switch_core_session *session, 
                                                                                                   char *file,
@@ -56,6 +142,7 @@ SWITCH_DECLARE(switch_status) switch_ivr_play_file(switch_core_session *session,
        int stream_id;
        switch_status status = SWITCH_STATUS_SUCCESS;
 
+       memset(&fh, 0, sizeof(fh));
 
        channel = switch_core_session_get_channel(session);
        assert(channel != NULL);
@@ -165,7 +252,9 @@ SWITCH_DECLARE(switch_status) switch_ivr_play_file(switch_core_session *session,
                        }
                } else { /* time off the channel (if you must) */
                        switch_frame *read_frame;
-                       switch_core_session_read_frame(session, &read_frame, -1, 0);
+                       if (switch_core_session_read_frame(session, &read_frame, -1, 0) != SWITCH_STATUS_SUCCESS) {
+                               break;
+                       }
                }
        }