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 {
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
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;
}
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;
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);
{
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;
}
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 = {
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;
- }
-
- 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;
+ switch_channel *channel;
+ channel = switch_core_session_get_channel(tech_pvt->session);
+ assert(channel != NULL);
- if (switch_core_codec_init(&tech_pvt->read_codec,
+ if (switch_core_codec_init(&tech_pvt->read_codec,
"L16",
sample_rate,
codec_ms,
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");
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;
}
}
+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)
{