mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-04-12 07:22:55 +00:00
make test 'record' app in app_playback.c
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
This commit is contained in:
parent
954fe31140
commit
48ae14726b
@ -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
|
||||
|
@ -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);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
@ -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 = {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/* 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, "r16")) {
|
||||
context->sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_PCM_16;
|
||||
context->sfinfo.channels = 1;
|
||||
context->sfinfo.samplerate = 16000;
|
||||
|
||||
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, "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 ((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 (!strcmp(ext, "gsm")) {
|
||||
context->sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_GSM610;
|
||||
context->sfinfo.channels = 1;
|
||||
context->sfinfo.samplerate = 8000;
|
||||
}
|
||||
|
||||
if (!(context->handle = sf_open(path, mode, &context->sfinfo))) {
|
||||
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Error Opening File [%s] [%s]\n", path,
|
||||
|
@ -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;
|
||||
|
@ -33,7 +33,93 @@
|
||||
#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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user