From 6e1f64207b82a9b2e79d04c1ffe19808a6953903 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 12 Dec 2005 21:01:17 +0000 Subject: [PATCH] let mod_portaudio get inbound calls git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@115 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- src/mod/mod_exosip/mod_exosip.c | 1 + src/mod/mod_iaxchan/mod_iaxchan.c | 14 +- src/mod/mod_playback/mod_playback.c | 6 +- src/mod/mod_portaudio/mod_portaudio.c | 211 ++++++++++++++++------ src/mod/mod_woomerachan/mod_woomerachan.c | 7 +- 5 files changed, 169 insertions(+), 70 deletions(-) diff --git a/src/mod/mod_exosip/mod_exosip.c b/src/mod/mod_exosip/mod_exosip.c index bcc5f07a25..b4196bee0c 100644 --- a/src/mod/mod_exosip/mod_exosip.c +++ b/src/mod/mod_exosip/mod_exosip.c @@ -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; } diff --git a/src/mod/mod_iaxchan/mod_iaxchan.c b/src/mod/mod_iaxchan/mod_iaxchan.c index 71a757e445..9f531c3eb7 100644 --- a/src/mod/mod_iaxchan/mod_iaxchan.c +++ b/src/mod/mod_iaxchan/mod_iaxchan.c @@ -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); diff --git a/src/mod/mod_playback/mod_playback.c b/src/mod/mod_playback/mod_playback.c index 02dc03b793..5d0efbb223 100644 --- a/src/mod/mod_playback/mod_playback.c +++ b/src/mod/mod_playback/mod_playback.c @@ -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"); diff --git a/src/mod/mod_portaudio/mod_portaudio.c b/src/mod/mod_portaudio/mod_portaudio.c index d659305949..9c8495ec8d 100644 --- a/src/mod/mod_portaudio/mod_portaudio.c +++ b/src/mod/mod_portaudio/mod_portaudio.c @@ -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 ", 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) { diff --git a/src/mod/mod_woomerachan/mod_woomerachan.c b/src/mod/mod_woomerachan/mod_woomerachan.c index 4325a5fc07..a1e05be8f0 100644 --- a/src/mod/mod_woomerachan/mod_woomerachan.c +++ b/src/mod/mod_woomerachan/mod_woomerachan.c @@ -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)