let mod_portaudio get inbound calls

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@115 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Anthony Minessale 2005-12-12 21:01:17 +00:00
parent 6fd5a33dbf
commit 6e1f64207b
5 changed files with 169 additions and 70 deletions

View File

@ -573,6 +573,7 @@ static switch_status exosip_read_frame(switch_core_session *session, switch_fram
samples = frames * tech_pvt->read_codec.implementation->samples_per_frame;
ms = frames * tech_pvt->read_codec.implementation->microseconds_per_frame;
tech_pvt->timestamp_recv += (int32_t)samples;
tech_pvt->read_frame.samples = samples;
break;
}

View File

@ -593,14 +593,11 @@ static switch_status channel_read_frame(switch_core_session *session, switch_fra
if (!switch_test_flag(tech_pvt, TFLAG_IO)) {
return SWITCH_STATUS_FALSE;
}
while (switch_test_flag(tech_pvt, TFLAG_IO) && !switch_test_flag(tech_pvt, TFLAG_VOICE)) {
switch_yield(1000);
}
if (switch_test_flag(tech_pvt, TFLAG_IO)) {
switch_clear_flag(tech_pvt, TFLAG_VOICE);
if(!tech_pvt->read_frame.datalen) {
continue;
break;
}
*frame = &tech_pvt->read_frame;
@ -907,10 +904,10 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_runtime(void)
switch_clear_flag(tech_pvt, TFLAG_IO);
switch_clear_flag(tech_pvt, TFLAG_VOICE);
if ((channel = switch_core_session_get_channel(tech_pvt->session))) {
switch_thread_cond_signal(tech_pvt->cond);
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Hangup %s\n", switch_channel_get_name(channel));
switch_set_flag(tech_pvt, TFLAG_HANGUP);
switch_channel_hangup(channel);
switch_thread_cond_signal(tech_pvt->cond);
iaxevent->session = NULL;
} else {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "No Session? %s\n", switch_test_flag(tech_pvt, TFLAG_VOICE) ? "yes" : "no");
@ -923,9 +920,10 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_runtime(void)
break;
case IAX_EVENT_VOICE:
if (tech_pvt && (tech_pvt->read_frame.datalen = iaxevent->datalen)) {
int bytes = tech_pvt->read_codec.implementation->encoded_bytes_per_frame;
int frames = (tech_pvt->read_frame.datalen / bytes);
tech_pvt->read_frame.samples = frames * tech_pvt->read_codec.implementation->samples_per_frame;
memcpy(tech_pvt->read_frame.data, iaxevent->data, iaxevent->datalen);
/* wake up the i/o thread*/
switch_set_flag(tech_pvt, TFLAG_VOICE);
switch_thread_cond_signal(tech_pvt->cond);

View File

@ -71,13 +71,17 @@ void playback_function(switch_core_session *session, char *data)
interval = 20;
len = 320;
samples = 160;
#if 0
interval = 30;
len = 480;
samples = 240;
#endif
write_frame.samples = samples;
/* You can use zap instead of soft if you have it loaded */
if (switch_core_timer_init(&timer, "soft", interval, samples) != SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "setup timer failed!\n");

View File

@ -52,7 +52,8 @@ typedef enum {
TFLAG_DTMF = (1 << 3),
TFLAG_VOICE = (1 << 4),
TFLAG_HANGUP = (1 << 5),
TFLAG_LINEAR = (1 << 6)
TFLAG_LINEAR = (1 << 6),
TFLAG_ANSWER = (1 << 7)
} TFLAGS;
typedef enum {
@ -104,13 +105,15 @@ static switch_status channel_outgoing_channel(switch_core_session *session, swit
static switch_status channel_read_frame(switch_core_session *session, switch_frame **frame, int timeout, switch_io_flag flags);
static switch_status channel_write_frame(switch_core_session *session, switch_frame *frame, int timeout, switch_io_flag flags);
static switch_status channel_kill_channel(switch_core_session *session, int sig);
static switch_status engage_device(struct private_object *tech_pvt);
static int dump_info(void);
static switch_status load_config(void);
static int get_dev_by_name(char *name, int in);
static switch_status place_call(char *dest, char *out, size_t outlen);
static switch_status hup_call(char *callid, char *out, size_t outlen);
static switch_status call_info(char *callid, char *out, size_t outlen);
static void send_dtmf(char *callid, char *out, size_t outlen);
static void answer_call(char *callid, char *out, size_t outlen);
/*
State methods they get called when the state changes to the specific state
@ -224,7 +227,34 @@ static switch_status channel_on_loopback(switch_core_session *session)
static switch_status channel_on_transmit(switch_core_session *session)
{
switch_channel *channel = NULL;
struct private_object *tech_pvt = NULL;
switch_time_t last;
int waitsec = 5 * 1000000;
channel = switch_core_session_get_channel(session);
assert(channel != NULL);
tech_pvt = switch_core_session_get_private(session);
assert(tech_pvt != NULL);
last = switch_time_now() - waitsec;
/* Turn on the device */
engage_device(tech_pvt);
while(switch_channel_get_state(channel) == CS_TRANSMIT && !switch_test_flag(tech_pvt, TFLAG_ANSWER)) {
if (switch_time_now() - last >= waitsec) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "BRRRRING! BRRRRING! call %s\n", tech_pvt->call_id);
last = switch_time_now();
}
switch_yield(50000);
}
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "CHANNEL TRANSMIT\n");
return SWITCH_STATUS_SUCCESS;
}
@ -264,8 +294,6 @@ static switch_status channel_outgoing_channel(switch_core_session *session, swit
return SWITCH_STATUS_GENERR;
}
//XXX outbound shit
/* (session == NULL) means it was originated from the core not from another channel */
if (session && (orig_channel = switch_core_session_get_channel(session))) {
switch_caller_profile *cloned_profile;
@ -275,7 +303,8 @@ static switch_status channel_outgoing_channel(switch_core_session *session, swit
switch_channel_set_originator_caller_profile(channel, cloned_profile);
}
}
switch_channel_set_flag(channel, CF_OUTBOUND);
switch_set_flag(tech_pvt, TFLAG_OUTBOUND);
switch_channel_set_state(channel, CS_INIT);
@ -323,16 +352,16 @@ static switch_status channel_read_frame(switch_core_session *session, switch_fra
{
switch_channel *channel = NULL;
struct private_object *tech_pvt = NULL;
int t;
int samples;
channel = switch_core_session_get_channel(session);
assert(channel != NULL);
tech_pvt = switch_core_session_get_private(session);
assert(tech_pvt != NULL);
if ((t = ReadAudioStream(tech_pvt->audio_in, tech_pvt->read_frame.data, tech_pvt->read_codec.implementation->samples_per_frame))) {
tech_pvt->read_frame.datalen = t * 2;
tech_pvt->read_frame.samples = t;
if ((samples = ReadAudioStream(tech_pvt->audio_in, tech_pvt->read_frame.data, tech_pvt->read_codec.implementation->samples_per_frame))) {
tech_pvt->read_frame.datalen = samples * 2;
tech_pvt->read_frame.samples = samples;
*frame = &tech_pvt->read_frame;
return SWITCH_STATUS_SUCCESS;
}
@ -384,11 +413,26 @@ static switch_status channel_answer_channel(switch_core_session *session)
return SWITCH_STATUS_SUCCESS;
}
static struct switch_api_interface send_dtmf_interface = {
/*.interface_name*/ "padtmf",
/*.desc*/ "PortAudio Dial DTMF",
/*.function*/ send_dtmf,
/*.next*/ NULL
};
static struct switch_api_interface answer_call_interface = {
/*.interface_name*/ "paoffhook",
/*.desc*/ "PortAudio Answer Call",
/*.function*/ answer_call,
/*.next*/ &send_dtmf_interface
};
static struct switch_api_interface channel_info_interface = {
/*.interface_name*/ "painfo",
/*.desc*/ "PortAudio Call Info",
/*.function*/ call_info,
/*.next*/ NULL
/*.next*/ &answer_call_interface
};
static struct switch_api_interface channel_hup_interface = {
@ -614,11 +658,67 @@ error:
return err;
}
static switch_status engage_device(struct private_object *tech_pvt)
{
int sample_rate = 8000;
int codec_ms = 20;
switch_channel *channel;
channel = switch_core_session_get_channel(tech_pvt->session);
assert(channel != NULL);
if (switch_core_codec_init(&tech_pvt->read_codec,
"L16",
sample_rate,
codec_ms,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
NULL) != SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n");
return SWITCH_STATUS_FALSE;
} else {
if (switch_core_codec_init(&tech_pvt->write_codec,
"L16",
sample_rate,
codec_ms,
SWITCH_CODEC_FLAG_ENCODE |SWITCH_CODEC_FLAG_DECODE, NULL) != SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n");
switch_core_codec_destroy(&tech_pvt->read_codec);
return SWITCH_STATUS_FALSE;
}
}
tech_pvt->read_frame.codec = &tech_pvt->read_codec;
switch_core_session_set_read_codec(tech_pvt->session, &tech_pvt->read_codec);
switch_core_session_set_write_codec(tech_pvt->session, &tech_pvt->write_codec);
tech_pvt->indev = globals.indev;
tech_pvt->outdev = globals.outdev;
if ((tech_pvt->err = OpenAudioStream( &tech_pvt->audio_in, sample_rate, SAMPLE_TYPE, PABLIO_READ | PABLIO_MONO, tech_pvt->indev, -1)) == paNoError) {
if ((tech_pvt->err = OpenAudioStream(&tech_pvt->audio_out, sample_rate, SAMPLE_TYPE, PABLIO_WRITE | PABLIO_MONO, -1, tech_pvt->outdev)) != paNoError) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't open audio out!\n");
CloseAudioStream(tech_pvt->audio_in);
}
} else {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't open audio in!\n");
}
if (tech_pvt->err == paNoError) {
snprintf(tech_pvt->call_id, sizeof(tech_pvt->call_id), "%d", globals.call_id++);
switch_core_hash_insert(globals.call_hash, tech_pvt->call_id, tech_pvt);
return SWITCH_STATUS_SUCCESS;
} else {
switch_core_codec_destroy(&tech_pvt->read_codec);
switch_core_codec_destroy(&tech_pvt->write_codec);
switch_core_session_destroy(&tech_pvt->session);
}
return SWITCH_STATUS_FALSE;
}
static switch_status place_call(char *dest, char *out, size_t outlen)
{
switch_core_session *session;
int sample_rate = 8000;
int codec_ms = 20;
switch_status status = SWITCH_STATUS_FALSE;
if (!dest) {
strncpy(out, "Usage: pacall <exten>", outlen - 1);
@ -627,7 +727,6 @@ static switch_status place_call(char *dest, char *out, size_t outlen)
strncpy(out, "FAIL", outlen - 1);
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "New Inbound Channel\n");
if ((session = switch_core_session_request(&channel_endpoint_interface, NULL))) {
struct private_object *tech_pvt;
switch_channel *channel;
@ -655,56 +754,13 @@ static switch_status place_call(char *dest, char *out, size_t outlen)
switch_channel_set_name(channel, name);
}
tech_pvt->session = session;
if (switch_core_codec_init(&tech_pvt->read_codec,
"L16",
sample_rate,
codec_ms,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
NULL) != SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n");
return SWITCH_STATUS_FALSE;
} else {
if (switch_core_codec_init(&tech_pvt->write_codec,
"L16",
sample_rate,
codec_ms,
SWITCH_CODEC_FLAG_ENCODE |SWITCH_CODEC_FLAG_DECODE, NULL) != SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n");
switch_core_codec_destroy(&tech_pvt->read_codec);
return SWITCH_STATUS_FALSE;
}
}
tech_pvt->read_frame.codec = &tech_pvt->read_codec;
switch_core_session_set_read_codec(tech_pvt->session, &tech_pvt->read_codec);
switch_core_session_set_write_codec(tech_pvt->session, &tech_pvt->write_codec);
tech_pvt->indev = globals.indev;
tech_pvt->outdev = globals.outdev;
if ((tech_pvt->err = OpenAudioStream( &tech_pvt->audio_in, sample_rate, SAMPLE_TYPE, PABLIO_READ | PABLIO_MONO, tech_pvt->indev, -1)) == paNoError) {
if ((tech_pvt->err = OpenAudioStream(&tech_pvt->audio_out, sample_rate, SAMPLE_TYPE, PABLIO_WRITE | PABLIO_MONO, -1, tech_pvt->outdev)) != paNoError) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't open audio out!\n");
CloseAudioStream(tech_pvt->audio_in);
}
} else {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't open audio in!\n");
}
if (tech_pvt->err == paNoError) {
if ((status = engage_device(tech_pvt)) == SWITCH_STATUS_SUCCESS) {
switch_channel_set_state(channel, CS_INIT);
snprintf(tech_pvt->call_id, sizeof(tech_pvt->call_id), "%d", globals.call_id++);
switch_core_hash_insert(globals.call_hash, tech_pvt->call_id, tech_pvt);
switch_core_session_thread_launch(session);
switch_core_session_thread_launch(tech_pvt->session);
snprintf(out, outlen, "SUCCESS: %s", tech_pvt->call_id);
return SWITCH_STATUS_SUCCESS;
} else {
switch_core_codec_destroy(&tech_pvt->read_codec);
switch_core_codec_destroy(&tech_pvt->write_codec);
switch_core_session_destroy(&session);
}
}
return SWITCH_STATUS_FALSE;
return status;
}
@ -752,6 +808,43 @@ static switch_status hup_call(char *callid, char *out, size_t outlen)
}
static void send_dtmf(char *callid, char *out, size_t outlen)
{
struct private_object *tech_pvt = NULL;
switch_channel *channel = NULL;
char *dtmf;
if (dtmf = strchr(callid, ' ')) {
*dtmf++ = '\0';
} else {
dtmf = "";
}
if ((tech_pvt = switch_core_hash_find(globals.call_hash, callid))) {
channel = switch_core_session_get_channel(tech_pvt->session);
assert(channel != NULL);
switch_channel_queue_dtmf(channel, dtmf);
strncpy(out, "OK", outlen - 1);
} else {
strncpy(out, "NO SUCH CALL", outlen - 1);
}
}
static void answer_call(char *callid, char *out, size_t outlen)
{
struct private_object *tech_pvt = NULL;
switch_channel *channel = NULL;
if ((tech_pvt = switch_core_hash_find(globals.call_hash, callid))) {
channel = switch_core_session_get_channel(tech_pvt->session);
assert(channel != NULL);
switch_set_flag(tech_pvt, TFLAG_ANSWER);
switch_channel_answer(channel);
} else {
strncpy(out, "NO SUCH CALL", outlen - 1);
}
}
static void print_info(struct private_object *tech_pvt, char *out, size_t outlen)
{

View File

@ -421,7 +421,7 @@ static switch_status woomerachan_read_frame(switch_core_session *session, switch
switch_channel *channel = NULL;
struct private_object *tech_pvt = NULL;
switch_frame *pframe;
//switch_status status;
switch_status status;
channel = switch_core_session_get_channel(session);
assert(channel != NULL);
@ -441,7 +441,10 @@ static switch_status woomerachan_read_frame(switch_core_session *session, switch
*frame = pframe;
pframe->datalen = sizeof(tech_pvt->databuf);
return switch_socket_recvfrom (tech_pvt->udpread, tech_pvt->udp_socket, 0, tech_pvt->databuf, &pframe->datalen);
if ((status = switch_socket_recvfrom (tech_pvt->udpread, tech_pvt->udp_socket, 0, tech_pvt->databuf, &pframe->datalen)) == SWITCH_STATUS_SUCCESS) {
pframe->samples = (int)pframe->datalen / 2;
}
return status;
}
static switch_status woomerachan_write_frame(switch_core_session *session, switch_frame *frame, int timeout, switch_io_flag flags)