[Freeswitch-branches] [commit] r10290 - freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax
Freeswitch SVN
gmaruzz at freeswitch.org
Fri Nov 7 11:42:50 PST 2008
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);
More information about the Freeswitch-branches
mailing list