]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
let mod_portaudio get inbound calls
authorAnthony Minessale <anthony.minessale@gmail.com>
Mon, 12 Dec 2005 21:01:17 +0000 (21:01 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Mon, 12 Dec 2005 21:01:17 +0000 (21:01 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@115 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/mod/mod_exosip/mod_exosip.c
src/mod/mod_iaxchan/mod_iaxchan.c
src/mod/mod_playback/mod_playback.c
src/mod/mod_portaudio/mod_portaudio.c
src/mod/mod_woomerachan/mod_woomerachan.c

index bcc5f07a25523996bba9cc7060df3af635e28cee..b4196bee0c1659f8122ae909f57139e991655ecd 100644 (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;
                        }
                        
index 71a757e445303a2adbe75d7604eec5fd15777206..9f531c3eb7bde7a6624def3ff93c66d6e2742b3a 100644 (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);
index 02dc03b793c9766f9e77b85cbac79cf76c297bb3..5d0efbb223a579843f7317427ba9722453a5e574 100644 (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");
index d6593059497e367cd21a8062675372d4bc041db6..9c8495ec8ddc10c0b11452849a27e82240dcd251 100644 (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,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;
-       }
-
-       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,
@@ -682,7 +693,7 @@ static switch_status place_call(char *dest, char *out, size_t outlen)
 
                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");
@@ -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)
 {
index 4325a5fc078fcb498bfded5296d9fce8d47efdf4..a1e05be8f0eaccc0432f6d694f49e249f8cb5820 100644 (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)