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

@ -73,11 +73,15 @@ void playback_function(switch_core_session *session, char *data)
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;
@ -276,6 +304,7 @@ static switch_status channel_outgoing_channel(switch_core_session *session, swit
}
}
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,49 +658,16 @@ error:
return err;
}
static switch_status place_call(char *dest, char *out, size_t outlen)
static switch_status engage_device(struct private_object *tech_pvt)
{
switch_core_session *session;
int sample_rate = 8000;
int codec_ms = 20;
if (!dest) {
strncpy(out, "Usage: pacall <exten>", outlen - 1);
return SWITCH_STATUS_FALSE;
}
switch_channel *channel;
channel = switch_core_session_get_channel(tech_pvt->session);
assert(channel != NULL);
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;
if ((tech_pvt = (struct private_object *) switch_core_session_alloc(session, sizeof(struct private_object)))) {
memset(tech_pvt, 0, sizeof(*tech_pvt));
channel = switch_core_session_get_channel(session);
switch_core_session_set_private(session, tech_pvt);
tech_pvt->session = session;
} else {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Hey where is my memory pool?\n");
switch_core_session_destroy(&session);
return SWITCH_STATUS_FALSE;
}
if ((tech_pvt->caller_profile = switch_caller_profile_new(session,
globals.dialplan,
globals.cid_name,
globals.cid_num,
NULL,
NULL,
dest))) {
char name[128];
switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
snprintf(name, sizeof(name), "PortAudio/%s-%04x", tech_pvt->caller_profile->destination_number, rand() & 0xffff);
switch_channel_set_name(channel, name);
}
tech_pvt->session = session;
if (switch_core_codec_init(&tech_pvt->read_codec,
if (switch_core_codec_init(&tech_pvt->read_codec,
"L16",
sample_rate,
codec_ms,
@ -692,19 +703,64 @@ static switch_status place_call(char *dest, char *out, size_t outlen)
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't open audio in!\n");
}
if (tech_pvt->err == paNoError) {
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);
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(&tech_pvt->session);
}
return SWITCH_STATUS_FALSE;
}
static switch_status place_call(char *dest, char *out, size_t outlen)
{
switch_core_session *session;
switch_status status = SWITCH_STATUS_FALSE;
if (!dest) {
strncpy(out, "Usage: pacall <exten>", outlen - 1);
return SWITCH_STATUS_FALSE;
}
strncpy(out, "FAIL", outlen - 1);
if ((session = switch_core_session_request(&channel_endpoint_interface, NULL))) {
struct private_object *tech_pvt;
switch_channel *channel;
if ((tech_pvt = (struct private_object *) switch_core_session_alloc(session, sizeof(struct private_object)))) {
memset(tech_pvt, 0, sizeof(*tech_pvt));
channel = switch_core_session_get_channel(session);
switch_core_session_set_private(session, tech_pvt);
tech_pvt->session = session;
} else {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Hey where is my memory pool?\n");
switch_core_session_destroy(&session);
return SWITCH_STATUS_FALSE;
}
if ((tech_pvt->caller_profile = switch_caller_profile_new(session,
globals.dialplan,
globals.cid_name,
globals.cid_num,
NULL,
NULL,
dest))) {
char name[128];
switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
snprintf(name, sizeof(name), "PortAudio/%s-%04x", tech_pvt->caller_profile->destination_number, rand() & 0xffff);
switch_channel_set_name(channel, name);
}
tech_pvt->session = session;
if ((status = engage_device(tech_pvt)) == SWITCH_STATUS_SUCCESS) {
switch_channel_set_state(channel, CS_INIT);
switch_core_session_thread_launch(tech_pvt->session);
snprintf(out, outlen, "SUCCESS: %s", tech_pvt->call_id);
}
}
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)