[commit] r10290 - freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax
Author: gmaruzz Date: Fri Nov 7 10:36:59 2008 New Revision: 10290 Modified: freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/mod_skypiax.c Log: skypiax: beginning initialization of Skype audio machinery Modified: freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/mod_skypiax.c ============================================================================== --- freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/mod_skypiax.c (original) +++ freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/mod_skypiax.c Fri Nov 7 10:36:59 2008 @@ -101,6 +101,43 @@ char type[256]; char X11_display[256]; struct AsteriskHandles AsteriskHandlesAst; + + int interface_state; /*!< \brief 'state' of the interface (channel) */ + char language[80]; /*!< \brief default Asterisk dialplan language for this interface */ + char exten[80]; /*!< \brief default Asterisk dialplan extension for this interface */ + int skypiax_sound_rate; /*!< \brief rate of the sound device, in Hz, eg: 8000 */ + int skypiax_sound_capt_fd; /*!< \brief file descriptor for sound capture dev */ + char callid_name[50]; + char callid_number[50]; + double playback_boost; + double capture_boost; + int stripmsd; + pthread_t skype_thread; + char skype_call_id[512]; + int skype_call_ongoing; + char skype_friends[4096]; + char skype_fullname[512]; + char skype_displayname[512]; + int skype_callflow; /*!< \brief 'callflow' of the skype interface (as opposed to phone interface) */ + int skype; /*!< \brief config flag, bool, Skype support on this interface (0 if false, -1 if true) */ + int control_to_send; + int audiopipe[2]; + int audioskypepipe[2]; + pthread_t tcp_srv_thread; + pthread_t tcp_cli_thread; + short audiobuf[160]; + int audiobuf_is_loaded; + + //int phonebook_listing; + //int phonebook_querying; + //int phonebook_listing_received_calls; + + //int phonebook_first_entry; + //int phonebook_last_entry; + //int phonebook_number_lenght; + //int phonebook_text_lenght; + FILE *phonebook_writing_fp; + int skypiax_dir_entry_extension_prefix; }; typedef struct skypiax_config skypiax_config_t; @@ -129,8 +166,302 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id); static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig); +int option_debug = 100; + +#define SKYPE_AUDIO +#ifdef SKYPE_AUDIO + +#define SAMPLES_PER_FRAME 160 +#define NN 160 +#define GG 160 +static void *SWITCH_THREAD_FUNC skypiax_do_tcp_srv_thread(switch_thread_t *thread, void *obj) +{ + struct skypiax_config *p = obj; + short in[GG]; + short out[GG / 2]; + int s, fd, len, sent; + unsigned int sin_size; + struct sockaddr_in my_addr; + struct sockaddr_in remote_addr; + int exit = 0; + int a; + int i; + + if (option_debug > 10) { + DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG); + } + memset(&my_addr, 0, sizeof(my_addr)); + my_addr.sin_family = AF_INET; + my_addr.sin_addr.s_addr = INADDR_ANY; + my_addr.sin_port = htons(5556); + + if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + ERRORA("socket Error\n", SKYPIAX_P_LOG); + if (option_debug > 10) { + DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG); + } + return NULL; + } + + if (bind(s, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) < 0) { + ERRORA("bind Error\n", SKYPIAX_P_LOG); + if (option_debug > 10) { + DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG); + } + return NULL; + } + DEBUGA_SKYPE("started tcp_srv_thread thread.\n", SKYPIAX_P_LOG); + + listen(s, 6); + + sin_size = sizeof(remote_addr); + while ((fd = accept(s, (struct sockaddr *) &remote_addr, &sin_size)) > 0) { + while (1) { + len = recv(fd, in, sizeof(short) * GG, 0); + if (len > 0) { + a = 0; + for (i = 0; i < len / sizeof(short); i++) { + out[a] = in[i]; + i++; + a++; + } + + if (!p->audiobuf_is_loaded) { + for (i = 0; i < (len / sizeof(short)) / 2; i++) { + p->audiobuf[i] = out[i]; + } + p->audiobuf_is_loaded = 1; + } else { + sent = write(p->audiopipe[1], p->audiobuf, len / 2); + sent = write(p->audiopipe[1], out, len / 2); + p->audiobuf_is_loaded = 0; + //DEBUGA_SOUND("read=====> req=%d recv=%d to sent=%d sent=%d\n", SKYPIAX_P_LOG, sizeof(short)*GG, len, (len*sizeof(short))/2, sent); + } + + } else if (len == 0) { + DEBUGA_SKYPE("client GONE\n", SKYPIAX_P_LOG); + break; + } else { + ERRORA("len=%d\n", SKYPIAX_P_LOG, len); + exit = 1; + break; + } + } + DEBUGA_SKYPE("client GONE\n", SKYPIAX_P_LOG); + close(fd); + if (exit) + break; + } + + DEBUGA_SKYPE("server (I am it) GONE\n", SKYPIAX_P_LOG); + close(s); + if (option_debug > 10) { + DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG); + } + return NULL; +} +void *skypiax_do_tcp_cli_thread(void *data) +{ + struct skypiax_config *p = data; + int s, fd, len; + short in[NN / 2]; + short out[NN]; + unsigned int sin_size; + struct sockaddr_in my_addr; + struct sockaddr_in remote_addr; + int a; + int i; + int got; + + if (option_debug > 10) { + DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG); + } + memset(&my_addr, 0, sizeof(my_addr)); + my_addr.sin_family = AF_INET; + my_addr.sin_addr.s_addr = INADDR_ANY; + my_addr.sin_port = htons(5558); + + if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + ERRORA("socket Error\n", SKYPIAX_P_LOG); + if (option_debug > 10) { + DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG); + } + return NULL; + } + + if (bind(s, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) < 0) { + ERRORA("bind Error\n", SKYPIAX_P_LOG); + if (option_debug > 10) { + DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG); + } + return NULL; + } + DEBUGA_SKYPE("started tcp_cli_thread thread.\n", SKYPIAX_P_LOG); + + listen(s, 6); + + sin_size = sizeof(remote_addr); + while ((fd = accept(s, (struct sockaddr *) &remote_addr, &sin_size)) > 0) { + DEBUGA_SKYPE("ACCEPTED\n", SKYPIAX_P_LOG); + //while (1 && p->owner && p->owner->_state == AST_STATE_UP) FIXME FIXME FIXME + while (1) { + + got = read(p->audioskypepipe[0], in, (NN / 2) * sizeof(short)); + + if (got > 0) { + a = 0; + for (i = 0; i < got / sizeof(short); i++) { + out[a] = in[i]; + a++; + out[a] = in[i]; + a++; + } + + len = send(fd, out, got * 2, 0); + + if (len == 0) { + DEBUGA_SKYPE("client GONE\n", SKYPIAX_P_LOG); + break; + } + } else { + usleep(100); + } + } + DEBUGA_SKYPE("client GONE\n", SKYPIAX_P_LOG); + close(fd); + } + DEBUGA_SKYPE("server (I am it) GONE\n", SKYPIAX_P_LOG); + close(s); + if (option_debug > 10) { + DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG); + } + return NULL; +} + + +int skypiax_skypeaudio_init(struct skypiax_config *p) +{ + int c; +/* build the pipe that will be polled on by pbx */ + c = pipe(p->audiopipe); + if (c) { + ERRORA("Unable to create audio pipe\n", SKYPIAX_P_LOG); + if (option_debug > 10) { + DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG); + } + return -1; + } + +/* the pipe is our audio fd for pbx to poll on */ + p->skypiax_sound_capt_fd = p->audiopipe[0]; + + /* let's start the serial monitoring thread too, so we can have serial signaling */ + +if(1) +{ + switch_thread_t *thread; + switch_threadattr_t *thd_attr = NULL; + + switch_threadattr_create(&thd_attr, module_pool); + switch_threadattr_detach_set(thd_attr, 1); + switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); + switch_thread_create(&thread, thd_attr, skypiax_do_tcp_srv_thread, p, module_pool); +} + +/* + if (ast_pthread_create(&p->tcp_srv_thread, NULL, skypiax_do_tcp_srv_thread, p) < 0) { + ERRORA("Unable to start tcp_srv_thread thread.\n", SKYPIAX_P_LOG); + if (option_debug > 10) { + DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG); + } + return -1; + } +*/ + + c = pipe(p->audioskypepipe); + if (c) { + ERRORA("Unable to create audioskypepipe\n", SKYPIAX_P_LOG); + if (option_debug > 10) { + DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG); + } + return -1; + } + fcntl(p->audioskypepipe[0], F_SETFL, O_NONBLOCK); + fcntl(p->audioskypepipe[1], F_SETFL, O_NONBLOCK); + + if (option_debug > 10) { + DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG); + } + return 0; +} +#ifdef NOTDEF +struct ast_frame *skypiax_skypeaudio_read(struct skypiax_config *p) +{ + static struct ast_frame f; + static short __buf[SKYPIAX_FRAME_SIZE + AST_FRIENDLY_OFFSET / 2]; + short *buf; + int samples; + + if (option_debug > 100) { + DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG); + } + memset(__buf, '\0', (SKYPIAX_FRAME_SIZE + AST_FRIENDLY_OFFSET / 2)); + + buf = __buf + AST_FRIENDLY_OFFSET / 2; + + f.frametype = AST_FRAME_NULL; + f.subclass = 0; + f.samples = 0; + f.datalen = 0; + f.data = NULL; + f.offset = 0; + f.src = skypiax_type; + f.mallocd = 0; + f.delivery.tv_sec = 0; + f.delivery.tv_usec = 0; + + if ((samples = read(p->audiopipe[0], buf, SAMPLES_PER_FRAME * sizeof(short))) != 320) { + DEBUGA_SOUND("read=====> NOT GOOD samples=%d expected=%d\n", SKYPIAX_P_LOG, samples, + SAMPLES_PER_FRAME * sizeof(short)); + usleep(100); + //do nothing + } else { + //DEBUGA_SOUND("read=====> GOOD samples=%d\n", SKYPIAX_P_LOG, samples); + /* A real frame */ + f.frametype = AST_FRAME_VOICE; + f.subclass = AST_FORMAT_SLINEAR; + f.samples = SKYPIAX_FRAME_SIZE; + f.datalen = SKYPIAX_FRAME_SIZE * 2; + f.data = buf; + f.offset = AST_FRIENDLY_OFFSET; + f.src = skypiax_type; + f.mallocd = 0; + } + + if (option_debug > 100) { + DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG); + } + return &f; +} +int skypiax_skypeaudio_write(struct skypiax_config *p, struct ast_frame *f) +{ + int sent; + + if (option_debug > 100) { + DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG); + } + sent = write(p->audioskypepipe[1], (short *) f->data, f->datalen); + + if (option_debug > 100) { + DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG); + } + return 0; +} +#endif //NOTDEF + +#endif /* SKYPE_AUDIO */ static void tech_init(private_t *tech_pvt, switch_core_session_t *session) { tech_pvt->read_frame.data = tech_pvt->databuf; @@ -946,6 +1277,11 @@ switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); switch_thread_create(&thread, thd_attr, do_skype_thread, &SKYPIAX_CONFIGS[span_id], module_pool); } + +usleep(1000000); + +skypiax_skypeaudio_init(&SKYPIAX_CONFIGS[span_id]); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "STARTED span_id=%d\n", span_id);
participants (1)
-
Freeswitch SVN