]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
skypiax: nothing to see here
authorGiovanni Maruzzelli <gmaruzz@gmail.com>
Sun, 14 Feb 2010 00:26:12 +0000 (00:26 +0000)
committerGiovanni Maruzzelli <gmaruzz@gmail.com>
Sun, 14 Feb 2010 00:26:12 +0000 (00:26 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@16636 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/mod/endpoints/mod_skypiax/109/1.diff [new file with mode: 0644]
src/mod/endpoints/mod_skypiax/109/dummy.c [new file with mode: 0644]
src/mod/endpoints/mod_skypiax/109/mod_skypiax.c [new file with mode: 0644]
src/mod/endpoints/mod_skypiax/109/skypiax.h [new file with mode: 0644]
src/mod/endpoints/mod_skypiax/109/skypiax_protocol.c [new file with mode: 0644]

diff --git a/src/mod/endpoints/mod_skypiax/109/1.diff b/src/mod/endpoints/mod_skypiax/109/1.diff
new file mode 100644 (file)
index 0000000..89d4cd8
--- /dev/null
@@ -0,0 +1,166 @@
+Index: skypiax_protocol.c
+===================================================================
+--- skypiax_protocol.c (revision 16633)
++++ skypiax_protocol.c (working copy)
+@@ -813,11 +813,14 @@
+                                       to.tv_usec = 60000;     //60 msec
+                                       to.tv_sec = 0;
++                                       if (tech_pvt->timer_read.timer_interface && tech_pvt->timer_read.timer_interface->timer_next) {
++      switch_core_timer_next(&tech_pvt->timer_read);
++                                       }
+                                       rt = select(fdselect + 1, &fs, NULL, NULL, &to);
+                                       if (rt > 0) {
+                                               if (tech_pvt->skype_callflow != CALLFLOW_STATUS_REMOTEHOLD) {
+-                                                      len = recv(fd, (char *) srv_in, 320, 0);        //seems that Skype only sends 320 bytes at time
++                                                      len = recv(fd, (char *) srv_in, 640, 0);        //seems that Skype only sends 320 bytes at time
+                                               } else {
+                                                       len = 0;
+                                               }
+@@ -825,6 +828,7 @@
+                                               if (len == 320) {
+                                                       unsigned int howmany;
++                                                              ERRORA("320!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n", SKYPIAX_P_LOG);
+                                                       if (samplerate_skypiax == 8000) {
+                                                               /* we're downsampling from 16khz to 8khz, srv_out will contain each other sample from srv_in */
+                                                               a = 0;
+@@ -869,10 +873,12 @@
+                                                               if (tech_pvt->flag_audio_srv == 1) {
+                                                                       switch_sleep(1000);     //1 millisec
+                                                               }
+-                                                              if (tech_pvt->flag_audio_srv == 0) {
++                                                              //if (tech_pvt->flag_audio_srv == 0) {
++                      switch_mutex_lock(tech_pvt->mutex_audio_srv);
+                                                                       memcpy(tech_pvt->audiobuf_srv, totalbuf, SAMPLES_PER_FRAME * sizeof(short));
+                                                                       tech_pvt->flag_audio_srv = 1;
+-                                                              }
++                      switch_mutex_unlock(tech_pvt->mutex_audio_srv);
++                                                              //}
+                                                               //NOTICA("read \n", SKYPIAX_P_LOG);
+                                                               if (howmany != SAMPLES_PER_FRAME * sizeof(short)) {
+                                                                       ERRORA("howmany is %d, but was expected to be %d\n", SKYPIAX_P_LOG,
+@@ -882,10 +888,19 @@
+                                                               tech_pvt->audiobuf_is_loaded = 0;
+                                                       }
++                                              } else if (len == 640) {
++
++                                                              if (tech_pvt->flag_audio_srv == 1) {
++                                                                      switch_sleep(1000);     //1 millisec
++                                                              }
++                      switch_mutex_lock(tech_pvt->mutex_audio_srv);
++                                                                      memcpy(tech_pvt->audiobuf_srv, srv_in, SAMPLES_PER_FRAME * sizeof(short));
++                                                                      tech_pvt->flag_audio_srv = 1;
++                      switch_mutex_unlock(tech_pvt->mutex_audio_srv);
+                                               } else if (len == 0) {
+                                                       skypiax_sleep(1000);
+                                               } else {
+-                                                      DEBUGA_SKYPE("len=%d, expected 320\n", SKYPIAX_P_LOG, len);
++                                                      ERRORA("len=%d, expected 640\n", SKYPIAX_P_LOG, len);
+                                               }
+                                       } else {
+@@ -1017,6 +1032,10 @@
+                                       int rt;
+                                       fd_set fs;
+                                       struct timeval to;
++                                      int waitin;
++                                      int big_waitin=40;
++                                      int lil_waitin=20;
++                                      int big_waited;
+                                       if (!(running && tech_pvt->running))
+                                               break;
+@@ -1040,15 +1059,37 @@
+                                       FD_SET(fdselect, &fs);
+                                       //FIXME rt = select(fdselect + 1, NULL, &fs, NULL, &to);
++                                      waitin=0;
++                                      big_waited=0;
+                                       while (tech_pvt->flag_audio_cli == 0) {
+ #ifdef WIN32
+                                               skypiax_sleep(100);     //0.1 millisec
+ #else
+                                               skypiax_sleep(1000);    //1 millisec
+ #endif //WIN32
+-                                              //WARNINGA("write now is 0\n", SKYPIAX_P_LOG);
++                                              waitin++;
++                                              if(big_waited == 1 && waitin==lil_waitin && tech_pvt->flag_audio_cli == 0){
++                                                      memset(cli_out, 255, SAMPLES_PER_FRAME * sizeof(short));
++                                                      send(fd, (char *) cli_out, SAMPLES_PER_FRAME * sizeof(short), 0);
++                                                      //WARNINGA("write buffer filled at %d\n", SKYPIAX_P_LOG, waitin);
++                                                      waitin=0;
++                                                      continue;
++                                              }
++                                              if(big_waited == 0 && waitin==big_waitin && tech_pvt->flag_audio_cli == 0){
++                                                      memset(cli_out, 255, SAMPLES_PER_FRAME * sizeof(short));
++                                                      send(fd, (char *) cli_out, SAMPLES_PER_FRAME * sizeof(short), 0);
++                                                      send(fd, (char *) cli_out, SAMPLES_PER_FRAME * sizeof(short), 0);
++                                                      WARNINGA("write buffer filled at %d\n", SKYPIAX_P_LOG, waitin);
++                                                      waitin=0;
++                                                      big_waited=1;
++                                                      continue;
++                                              }
++
+                                       }
+-                                      //ERRORA("write is now 1\n", SKYPIAX_P_LOG);
++                                      if(waitin > 21)
++                                              ERRORA("waitin is now %d\n", SKYPIAX_P_LOG, waitin);
++                                      if(!waitin)
++                                      NOTICA("waitin is now %d\n", SKYPIAX_P_LOG, waitin);
+                                       rt = 1;
+@@ -1149,22 +1190,28 @@
+ int skypiax_audio_read(private_t * tech_pvt)
+ {
+       unsigned int samples;
++      int waitin;
++      waitin=0;
+       while (tech_pvt->flag_audio_srv == 0) {
+ #ifdef WIN32
+               skypiax_sleep(100);             //0.1 millisec
+ #else
+               skypiax_sleep(1000);    //1 millisec
+ #endif //WIN32
++              waitin++;
+               //WARNINGA("read now is 0\n", SKYPIAX_P_LOG);
+       }
+-      //ERRORA("read is now 1\n", SKYPIAX_P_LOG);
++      if(waitin > 21)
++      NOTICA("read is now %d\n", SKYPIAX_P_LOG, waitin);
+       //samples = skypiax_pipe_read(tech_pvt->audiopipe_srv[0], tech_pvt->read_frame.data, SAMPLES_PER_FRAME * sizeof(short));
+-      samples = SAMPLES_PER_FRAME * sizeof(short);
++                      switch_mutex_lock(tech_pvt->mutex_audio_srv);
+       memcpy(tech_pvt->read_frame.data, tech_pvt->audiobuf_srv, SAMPLES_PER_FRAME * sizeof(short));
+       tech_pvt->flag_audio_srv = 0;
++                      switch_mutex_unlock(tech_pvt->mutex_audio_srv);
++      samples = SAMPLES_PER_FRAME * sizeof(short);
+       if (samples != SAMPLES_PER_FRAME * sizeof(short)) {
+               if (samples)
+                       WARNINGA("read samples=%u expected=%u\n", SKYPIAX_P_LOG, samples, (int) (SAMPLES_PER_FRAME * sizeof(short)));
+Index: mod_skypiax.c
+===================================================================
+--- mod_skypiax.c      (revision 16633)
++++ mod_skypiax.c      (working copy)
+@@ -719,7 +719,6 @@
+                               DEBUGA_SKYPE("CHANNEL READ CONTINUE\n", SKYPIAX_P_LOG);
+                               continue;
+                       }
+-                      switch_core_timer_check(&tech_pvt->timer_read, SWITCH_TRUE);
+                       *frame = &tech_pvt->read_frame;
+ #if SWITCH_BYTE_ORDER == __BIG_ENDIAN
+                       if (switch_test_flag(tech_pvt, TFLAG_LINEAR)) {
+@@ -1393,6 +1392,7 @@
+                               switch_sleep(100000);
+                               skypiax_audio_init(&globals.SKYPIAX_INTERFACES[interface_id]);
++                              switch_mutex_init(&globals.SKYPIAX_INTERFACES[interface_id].mutex_audio_srv, SWITCH_MUTEX_NESTED, skypiax_module_pool);
+                               NOTICA
+                                       ("WAITING roughly 10 seconds to find a running Skype client and connect to its SKYPE API for interface_id=%d\n",
diff --git a/src/mod/endpoints/mod_skypiax/109/dummy.c b/src/mod/endpoints/mod_skypiax/109/dummy.c
new file mode 100644 (file)
index 0000000..df36e11
--- /dev/null
@@ -0,0 +1,937 @@
+/*
+ *  Dummy soundcard
+ *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#include <sound/driver.h>              //giova
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/jiffies.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/wait.h>
+#include <linux/moduleparam.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/tlv.h>
+#include <sound/pcm.h>
+#include <sound/rawmidi.h>
+#include <sound/initval.h>
+
+
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
+MODULE_DESCRIPTION("Dummy soundcard (/dev/null)");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{ALSA,Dummy soundcard}}");
+
+#define MAX_PCM_DEVICES                4
+#define MAX_PCM_SUBSTREAMS     128
+#define MAX_MIDI_DEVICES       2
+
+#if 0                                                  /* emu10k1 emulation */
+#define MAX_BUFFER_SIZE                (128 * 1024)
+static int emu10k1_playback_constraints(struct snd_pcm_runtime *runtime)
+{
+       int err;
+       err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+       if (err < 0)
+               return err;
+       err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 256, UINT_MAX);
+       if (err < 0)
+               return err;
+       return 0;
+}
+
+#define add_playback_constraints emu10k1_playback_constraints
+#endif
+
+#if 0                                                  /* RME9652 emulation */
+#define MAX_BUFFER_SIZE                (26 * 64 * 1024)
+#define USE_FORMATS            SNDRV_PCM_FMTBIT_S32_LE
+#define USE_CHANNELS_MIN       26
+#define USE_CHANNELS_MAX       26
+#define USE_PERIODS_MIN                2
+#define USE_PERIODS_MAX                2
+#endif
+
+#if 0                                                  /* ICE1712 emulation */
+#define MAX_BUFFER_SIZE                (256 * 1024)
+#define USE_FORMATS            SNDRV_PCM_FMTBIT_S32_LE
+#define USE_CHANNELS_MIN       10
+#define USE_CHANNELS_MAX       10
+#define USE_PERIODS_MIN                1
+#define USE_PERIODS_MAX                1024
+#endif
+
+#if 0                                                  /* UDA1341 emulation */
+#define MAX_BUFFER_SIZE                (16380)
+#define USE_FORMATS            SNDRV_PCM_FMTBIT_S16_LE
+#define USE_CHANNELS_MIN       2
+#define USE_CHANNELS_MAX       2
+#define USE_PERIODS_MIN                2
+#define USE_PERIODS_MAX                255
+#endif
+
+#if 0                                                  /* simple AC97 bridge (intel8x0) with 48kHz AC97 only codec */
+#define USE_FORMATS            SNDRV_PCM_FMTBIT_S16_LE
+#define USE_CHANNELS_MIN       2
+#define USE_CHANNELS_MAX       2
+#define USE_RATE               SNDRV_PCM_RATE_48000
+#define USE_RATE_MIN           48000
+#define USE_RATE_MAX           48000
+#endif
+
+#if 0                                                  /* CA0106 */
+#define USE_FORMATS            SNDRV_PCM_FMTBIT_S16_LE
+#define USE_CHANNELS_MIN       2
+#define USE_CHANNELS_MAX       2
+#define USE_RATE               (SNDRV_PCM_RATE_48000|SNDRV_PCM_RATE_96000|SNDRV_PCM_RATE_192000)
+#define USE_RATE_MIN           48000
+#define USE_RATE_MAX           192000
+#define MAX_BUFFER_SIZE                ((65536-64)*8)
+#define MAX_PERIOD_SIZE                (65536-64)
+#define USE_PERIODS_MIN                2
+#define USE_PERIODS_MAX                8
+#endif
+
+
+/* defaults */
+#ifndef MAX_BUFFER_SIZE
+#define MAX_BUFFER_SIZE                (64*1024)
+#endif
+#ifndef MAX_PERIOD_SIZE
+#define MAX_PERIOD_SIZE                MAX_BUFFER_SIZE
+#endif
+#ifndef USE_FORMATS
+#define USE_FORMATS            (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE)
+#endif
+#ifndef USE_RATE
+#define USE_RATE               SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000
+#define USE_RATE_MIN           5500
+#define USE_RATE_MAX           48000
+#endif
+#ifndef USE_CHANNELS_MIN
+#define USE_CHANNELS_MIN       1
+#endif
+#ifndef USE_CHANNELS_MAX
+#define USE_CHANNELS_MAX       2
+#endif
+#ifndef USE_PERIODS_MIN
+#define USE_PERIODS_MIN        1
+#endif
+#ifndef USE_PERIODS_MAX
+#define USE_PERIODS_MAX        1024
+#endif
+#ifndef add_playback_constraints
+#define add_playback_constraints(x) 0
+#endif
+#ifndef add_capture_constraints
+#define add_capture_constraints(x) 0
+#endif
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;     /* Index 0-MAX */
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;      /* ID for this card */
+static int enable[SNDRV_CARDS] = { 1,[1 ... (SNDRV_CARDS - 1)] = 0 };
+static int pcm_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1 };
+static int pcm_substreams[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 128 };
+
+//static int midi_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for dummy soundcard.");
+module_param_array(id, charp, NULL, 0444);
+MODULE_PARM_DESC(id, "ID string for dummy soundcard.");
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable this dummy soundcard.");
+module_param_array(pcm_devs, int, NULL, 0444);
+MODULE_PARM_DESC(pcm_devs, "PCM devices # (0-4) for dummy driver.");
+module_param_array(pcm_substreams, int, NULL, 0444);
+MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-64) for dummy driver.");
+//module_param_array(midi_devs, int, NULL, 0444);
+//MODULE_PARM_DESC(midi_devs, "MIDI devices # (0-2) for dummy driver.");
+
+static struct platform_device *devices[SNDRV_CARDS];
+static struct timer_list giovatimer;   //giova
+static int giovastarted = 0;
+static int giovaindex = 0;
+static spinlock_t giovalock;
+struct giovadpcm {
+       struct snd_pcm_substream *substream;
+       struct snd_dummy_pcm *dpcm;
+       int started;
+};
+static struct giovadpcm giovadpcms[MAX_PCM_SUBSTREAMS];
+
+#define MIXER_ADDR_MASTER      0
+#define MIXER_ADDR_LINE                1
+#define MIXER_ADDR_MIC         2
+#define MIXER_ADDR_SYNTH       3
+#define MIXER_ADDR_CD          4
+#define MIXER_ADDR_LAST                4
+
+static void snd_card_dummy_pcm_timer_function(unsigned long data);
+struct snd_dummy {
+       struct snd_card *card;
+       struct snd_pcm *pcm;
+       spinlock_t mixer_lock;
+       int mixer_volume[MIXER_ADDR_LAST + 1][2];
+       int capture_source[MIXER_ADDR_LAST + 1][2];
+};
+
+struct snd_dummy_pcm {
+       struct snd_dummy *dummy;
+       spinlock_t lock;
+       struct timer_list timer;
+       unsigned int pcm_buffer_size;
+       unsigned int pcm_period_size;
+       unsigned int pcm_bps;           /* bytes per second */
+       unsigned int pcm_hz;            /* HZ */
+       unsigned int pcm_irq_pos;       /* IRQ position */
+       unsigned int pcm_buf_pos;       /* position in buffer */
+       struct snd_pcm_substream *substream;
+};
+
+
+static inline void snd_card_dummy_pcm_timer_start(struct snd_dummy_pcm *dpcm)
+{
+       int i;
+       int found = 0;
+
+
+//printk("giova: 1 timer_start %d %p\n", __LINE__, dpcm);
+       for (i = 0; i < giovaindex + 1; i++) {
+               if (i > MAX_PCM_SUBSTREAMS || giovaindex > MAX_PCM_SUBSTREAMS) {
+                       printk("giova, %s:%d, i=%d, giovaindex=%d dpcm=%p\n", __FILE__, __LINE__, i, giovaindex, dpcm);
+               }
+
+               if (giovadpcms[i].dpcm == dpcm) {
+                       giovadpcms[i].started = 1;
+                       found = 1;
+               }
+       }
+       if (!found) {
+               printk("skypiax: start, NOT found?\n");
+       }
+
+//printk("giova: 2 timer_start %d %p\n", __LINE__, dpcm);
+}
+
+static inline void snd_card_dummy_pcm_timer_stop(struct snd_dummy_pcm *dpcm)
+{
+       //del_timer(&dpcm->timer);
+       int i;
+       int found = 0;
+
+//printk("giova: 1 timer_stop %d %p\n", __LINE__, dpcm);
+       for (i = 0; i < giovaindex + 1; i++) {
+
+               if (i > MAX_PCM_SUBSTREAMS || giovaindex > MAX_PCM_SUBSTREAMS) {
+                       printk("giova, %s:%d, i=%d, giovaindex=%d dpcm=%p\n", __FILE__, __LINE__, i, giovaindex, dpcm);
+               }
+               if (giovadpcms[i].dpcm == dpcm) {
+                       giovadpcms[i].started = 0;
+                       found = 1;
+               }
+       }
+       if (!found) {
+               //printk("skypiax: stop, NOT found?\n");
+       } else {
+               //printk("skypiax: stop, YES found!\n"); 
+       }
+
+
+
+//printk("giova: 2 timer_stop %d %p\n", __LINE__, dpcm);
+}
+
+static int snd_card_dummy_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct snd_dummy_pcm *dpcm = runtime->private_data;
+       int err = 0;
+
+       //spin_lock(&dpcm->lock, flags);
+       spin_lock_bh(&giovalock);
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+//printk("giova: trigger timer_start %d %p\n", __LINE__, dpcm);
+               snd_card_dummy_pcm_timer_start(dpcm);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+//printk("giova: trigger timer_stop %d %p\n", __LINE__, dpcm);
+               snd_card_dummy_pcm_timer_stop(dpcm);
+               break;
+       default:
+               err = -EINVAL;
+               break;
+       }
+       //spin_unlock(&dpcm->lock, flags);
+       spin_unlock_bh(&giovalock);
+       return 0;
+}
+
+static int snd_card_dummy_pcm_prepare(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct snd_dummy_pcm *dpcm = runtime->private_data;
+       int bps;
+
+       bps = snd_pcm_format_width(runtime->format) * runtime->rate * runtime->channels / 8;
+
+       if (bps <= 0)
+               return -EINVAL;
+
+       dpcm->pcm_bps = bps;
+       dpcm->pcm_hz = HZ;
+       dpcm->pcm_buffer_size = snd_pcm_lib_buffer_bytes(substream);
+       dpcm->pcm_period_size = snd_pcm_lib_period_bytes(substream);
+       dpcm->pcm_irq_pos = 0;
+       dpcm->pcm_buf_pos = 0;
+       snd_pcm_format_set_silence(runtime->format, runtime->dma_area, bytes_to_samples(runtime, runtime->dma_bytes));
+
+//printk("giova: prepare %d %p\n", __LINE__, dpcm);
+       return 0;
+}
+
+static void snd_card_dummy_pcm_timer_function(unsigned long data)
+{
+       //struct snd_dummy_pcm *dpcm = (struct snd_dummy_pcm *)data;
+       struct snd_dummy_pcm *dpcm = NULL;
+       //unsigned long flags;
+       int i;
+
+
+       giovatimer.expires = (HZ / 100) + jiffies;
+       add_timer(&giovatimer);
+
+       for (i = 0; i < giovaindex + 1; i++) {
+
+               if (i > MAX_PCM_SUBSTREAMS || giovaindex > MAX_PCM_SUBSTREAMS) {
+                       printk("giova, %s:%d, i=%d, giovaindex=%d dpcm=%p\n", __FILE__, __LINE__, i, giovaindex, dpcm);
+               }
+//printk("giova: timer_func %d i=%d\n", __LINE__, i);
+
+               if (giovadpcms[i].started != 1)
+                       continue;
+               dpcm = giovadpcms[i].dpcm;
+               if (dpcm == NULL) {
+                       printk("giova: timer_func %d %d NULL: continue\n", __LINE__, i);
+                       continue;
+               }
+               //if (in_irq())
+                       //printk("giova: timer_func %d %d we are in HARDWARE IRQ\n", __LINE__, i);
+               //if(in_softirq())
+               //printk("giova: timer_func %d %d we are in SOFT IRQ\n", __LINE__, i);
+//printk("giova: timer_func %d %d\n", __LINE__, i);
+               //spin_lock_irqsave(&dpcm->lock, flags);
+               spin_lock_bh(&dpcm->lock);
+               dpcm->pcm_irq_pos += dpcm->pcm_bps * (HZ / 100);
+               dpcm->pcm_buf_pos += dpcm->pcm_bps * (HZ / 100);
+               dpcm->pcm_buf_pos %= dpcm->pcm_buffer_size * dpcm->pcm_hz;
+               if (dpcm->pcm_irq_pos >= dpcm->pcm_period_size * dpcm->pcm_hz) {
+                       dpcm->pcm_irq_pos %= dpcm->pcm_period_size * dpcm->pcm_hz;
+                       //spin_unlock_irqrestore(&dpcm->lock, flags);
+                       spin_unlock_bh(&dpcm->lock);
+                       snd_pcm_period_elapsed(dpcm->substream);
+               } else {
+                       //spin_unlock_irqrestore(&dpcm->lock, flags);
+                       spin_unlock_bh(&dpcm->lock);
+               }
+       }
+}
+
+static snd_pcm_uframes_t snd_card_dummy_pcm_pointer(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct snd_dummy_pcm *dpcm = runtime->private_data;
+
+//printk("giova: pointer %d %p\n", __LINE__, dpcm);
+       return bytes_to_frames(runtime, dpcm->pcm_buf_pos / dpcm->pcm_hz);
+       //return (dpcm->pcm_buf_pos / dpcm->pcm_hz) / 2;
+}
+
+static struct snd_pcm_hardware snd_card_dummy_playback = {
+       .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID),
+       .formats = USE_FORMATS,
+       .rates = USE_RATE,
+       .rate_min = USE_RATE_MIN,
+       .rate_max = USE_RATE_MAX,
+       .channels_min = USE_CHANNELS_MIN,
+       .channels_max = USE_CHANNELS_MAX,
+       .buffer_bytes_max = MAX_BUFFER_SIZE,
+       .period_bytes_min = 64,
+       .period_bytes_max = MAX_PERIOD_SIZE,
+       .periods_min = USE_PERIODS_MIN,
+       .periods_max = USE_PERIODS_MAX,
+       .fifo_size = 0,
+};
+
+static struct snd_pcm_hardware snd_card_dummy_capture = {
+       .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID),
+       .formats = USE_FORMATS,
+       .rates = USE_RATE,
+       .rate_min = USE_RATE_MIN,
+       .rate_max = USE_RATE_MAX,
+       .channels_min = USE_CHANNELS_MIN,
+       .channels_max = USE_CHANNELS_MAX,
+       .buffer_bytes_max = MAX_BUFFER_SIZE,
+       .period_bytes_min = 64,
+       .period_bytes_max = MAX_PERIOD_SIZE,
+       .periods_min = USE_PERIODS_MIN,
+       .periods_max = USE_PERIODS_MAX,
+       .fifo_size = 0,
+};
+
+static void snd_card_dummy_runtime_free(struct snd_pcm_runtime *runtime)
+{
+       int i;
+//int found=0;
+
+//printk("snd_card_dummy_runtime_free giova 1 giovaindex=%d dpcm=%p runtime=%p\n", giovaindex, runtime->private_data, runtime);
+       spin_lock_bh(&giovalock);
+
+       for (i = 0; i < giovaindex; i++) {
+
+               if (i > MAX_PCM_SUBSTREAMS || giovaindex > MAX_PCM_SUBSTREAMS) {
+                       printk("giova, %s:%d, i=%d, giovaindex=%d \n", __FILE__, __LINE__, i, giovaindex);
+               }
+               //if((giovadpcms[i].substream == substream)  && (giovadpcms[i].dpcm == dpcm)){
+               if ((giovadpcms[i].dpcm == runtime->private_data)) {
+                       //printk("giova, %s:%d, i=%d, giovaindex=%d %p==%p YES I AM!!!!\n", __FILE__, __LINE__, i, giovaindex, giovadpcms[i].dpcm , runtime->private_data);
+                       //giovadpcms[i].dpcm = NULL;
+                       //giovadpcms[i].substream = NULL;
+                       giovadpcms[i].started = 0;
+                       //break;
+               } else {
+                       //printk("giova, %s:%d, i=%d, giovaindex=%d %p!=%p NOT ME\n", __FILE__, __LINE__, i, giovaindex, giovadpcms[i].dpcm , runtime->private_data);
+               }
+       }
+
+       spin_unlock_bh(&giovalock);
+       kfree(runtime->private_data);
+}
+
+static int snd_card_dummy_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params)
+{
+       return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
+}
+
+static int snd_card_dummy_hw_free(struct snd_pcm_substream *substream)
+{
+       return snd_pcm_lib_free_pages(substream);
+}
+
+static struct snd_dummy_pcm *new_pcm_stream(struct snd_pcm_substream *substream)
+{
+       struct snd_dummy_pcm *dpcm;
+       int i;
+       int found = 0;
+
+       //printk("giova, %s:%d, i=%d, giovaindex=%d %p==%p YES I AM!!!!\n", __FILE__, __LINE__, i, giovaindex, giovadpcms[i].dpcm , runtime->private_data);
+       //printk("giova, %s:%d, giovaindex=%d\n", __FILE__, __LINE__, giovaindex);
+       dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL);
+       //printk("giova, %s:%d, giovaindex=%d\n", __FILE__, __LINE__, giovaindex);
+       if (!dpcm) {
+               //spin_unlock_bh(&giovalock);
+               printk("giova, %s:%d, giovaindex=%d NO MEMORY!!!!\n", __FILE__, __LINE__, giovaindex);
+               return dpcm;
+       }
+       //printk("giova, %s:%d, giovaindex=%d dpcm=%p\n", __FILE__, __LINE__, giovaindex, dpcm);
+       init_timer(&dpcm->timer);
+       //dpcm->timer.data = (unsigned long) dpcm;
+       //dpcm->timer.function = snd_card_dummy_pcm_timer_function;
+       spin_lock_init(&dpcm->lock);
+       dpcm->substream = substream;
+
+       spin_lock_bh(&giovalock);
+       //printk("giova 1 giovaindex=%d dpcm=%p substream=%p sizeof=%lu\n", giovaindex, dpcm, substream, sizeof(*dpcm));
+       for (i = 0; i < giovaindex; i++) {
+
+               if (i > MAX_PCM_SUBSTREAMS || giovaindex > MAX_PCM_SUBSTREAMS) {
+                       printk("giova, %s:%d, i=%d, giovaindex=%d dpcm=%p\n", __FILE__, __LINE__, i, giovaindex, dpcm);
+               }
+               //if((giovadpcms[i].substream == substream)  && (giovadpcms[i].dpcm == dpcm))
+               if ((giovadpcms[i].substream == substream)) {
+                       found = 1;
+                       break;
+               }
+
+       }
+
+       if (!found) {
+
+               giovadpcms[giovaindex].substream = substream;
+               giovaindex++;
+               //printk("giova 2 giovaindex=%d dpcm=%p substream=%p\n", giovaindex, dpcm, substream);
+       }
+
+
+
+       found = 0;
+       for (i = 0; i < giovaindex; i++) {
+
+               if (i > MAX_PCM_SUBSTREAMS || giovaindex > MAX_PCM_SUBSTREAMS) {
+                       printk("giova, %s:%d, i=%d, giovaindex=%d dpcm=%p\n", __FILE__, __LINE__, i, giovaindex, dpcm);
+               }
+               if (giovadpcms[i].substream == substream) {
+                       giovadpcms[i].dpcm = dpcm;
+                       giovadpcms[i].started = 0;
+                       found = 1;
+                       //printk("giova 3 giovaindex=%d dpcm=%p substream=%p\n", giovaindex, dpcm, substream);
+                       break;
+               }
+
+       }
+
+       spin_unlock_bh(&giovalock);
+       if (!found) {
+               printk("skypiax giovaindex=%d NOT found????\n", giovaindex);
+       }
+       //printk("giova, %s:%d, giovaindex=%d\n", __FILE__, __LINE__, giovaindex);
+       return dpcm;
+}
+
+static int snd_card_dummy_playback_open(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct snd_dummy_pcm *dpcm;
+       int err;
+
+       if ((dpcm = new_pcm_stream(substream)) == NULL)
+               return -ENOMEM;
+       //printk("giova, %s:%d, giovaindex=%d dpcm=%p\n", __FILE__, __LINE__, giovaindex, dpcm);
+       runtime->private_data = dpcm;
+       /* makes the infrastructure responsible for freeing dpcm */
+       runtime->private_free = snd_card_dummy_runtime_free;
+       runtime->hw = snd_card_dummy_playback;
+       if (substream->pcm->device & 1) {
+               runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED;
+               runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED;
+       }
+       if (substream->pcm->device & 2)
+               runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID);
+       err = add_playback_constraints(runtime);
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+static int snd_card_dummy_capture_open(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct snd_dummy_pcm *dpcm;
+       int err;
+
+       if ((dpcm = new_pcm_stream(substream)) == NULL)
+               return -ENOMEM;
+       //printk("giova, %s:%d, giovaindex=%d dpcm=%p\n", __FILE__, __LINE__, giovaindex, dpcm);
+       runtime->private_data = dpcm;
+       /* makes the infrastructure responsible for freeing dpcm */
+       runtime->private_free = snd_card_dummy_runtime_free;
+       runtime->hw = snd_card_dummy_capture;
+       if (substream->pcm->device == 1) {
+               runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED;
+               runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED;
+       }
+       if (substream->pcm->device & 2)
+               runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID);
+       err = add_capture_constraints(runtime);
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+static int snd_card_dummy_playback_close(struct snd_pcm_substream *substream)
+{
+//printk("play giova 1 giovaindex=%d dpcm=%p substream=%p\n", giovaindex, substream->private_data, substream);
+       snd_card_dummy_pcm_timer_stop(substream->private_data);
+       return 0;
+}
+
+static int snd_card_dummy_capture_close(struct snd_pcm_substream *substream)
+{
+//printk("capt giova 2 giovaindex=%d dpcm=%p substream=%p\n", giovaindex, substream->private_data, substream);
+       snd_card_dummy_pcm_timer_stop(substream->private_data);
+       return 0;
+}
+
+static struct snd_pcm_ops snd_card_dummy_playback_ops = {
+       .open = snd_card_dummy_playback_open,
+       .close = snd_card_dummy_playback_close,
+       .ioctl = snd_pcm_lib_ioctl,
+       .hw_params = snd_card_dummy_hw_params,
+       .hw_free = snd_card_dummy_hw_free,
+       .prepare = snd_card_dummy_pcm_prepare,
+       .trigger = snd_card_dummy_pcm_trigger,
+       .pointer = snd_card_dummy_pcm_pointer,
+};
+
+static struct snd_pcm_ops snd_card_dummy_capture_ops = {
+       .open = snd_card_dummy_capture_open,
+       .close = snd_card_dummy_capture_close,
+       .ioctl = snd_pcm_lib_ioctl,
+       .hw_params = snd_card_dummy_hw_params,
+       .hw_free = snd_card_dummy_hw_free,
+       .prepare = snd_card_dummy_pcm_prepare,
+       .trigger = snd_card_dummy_pcm_trigger,
+       .pointer = snd_card_dummy_pcm_pointer,
+};
+
+static int __devinit snd_card_dummy_pcm(struct snd_dummy *dummy, int device, int substreams)
+{
+       struct snd_pcm *pcm;
+       int err;
+
+       err = snd_pcm_new(dummy->card, "Dummy PCM", device, substreams, substreams, &pcm);
+       if (err < 0)
+               return err;
+       dummy->pcm = pcm;
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_card_dummy_playback_ops);
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_card_dummy_capture_ops);
+       pcm->private_data = dummy;
+       pcm->info_flags = 0;
+       strcpy(pcm->name, "Dummy PCM");
+       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data(GFP_KERNEL), 128 * 1024, 1024 * 1024);
+
+       return 0;
+}
+
+#define DUMMY_VOLUME(xname, xindex, addr) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+  .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
+  .name = xname, .index = xindex, \
+  .info = snd_dummy_volume_info, \
+  .get = snd_dummy_volume_get, .put = snd_dummy_volume_put, \
+  .private_value = addr, \
+  .tlv = { .p = db_scale_dummy } }
+
+static int snd_dummy_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 2;
+       uinfo->value.integer.min = -50;
+       uinfo->value.integer.max = 100;
+       return 0;
+}
+
+static int snd_dummy_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol);
+       int addr = kcontrol->private_value;
+       //unsigned long flags;
+
+       if (in_irq())
+               printk("giova: line %d we are in HARDWARE IRQ\n", __LINE__);
+//printk("giova: volume get %d %d\n", __LINE__, addr);
+       //spin_lock_irq(&dummy->mixer_lock);
+       //spin_lock_irqsave(&dummy->mixer_lock, flags);
+       spin_lock_bh(&dummy->mixer_lock);
+       ucontrol->value.integer.value[0] = dummy->mixer_volume[addr][0];
+       ucontrol->value.integer.value[1] = dummy->mixer_volume[addr][1];
+       //spin_unlock_irqrestore(&dummy->mixer_lock, flags);
+       spin_unlock_bh(&dummy->mixer_lock);
+       return 0;
+}
+
+static int snd_dummy_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol);
+       int change, addr = kcontrol->private_value;
+       int left, right;
+       //unsigned long flags;
+
+       if (in_irq())
+               printk("giova: line %d we are in HARDWARE IRQ\n", __LINE__);
+       left = ucontrol->value.integer.value[0];
+       if (left < -50)
+               left = -50;
+       if (left > 100)
+               left = 100;
+       right = ucontrol->value.integer.value[1];
+       if (right < -50)
+               right = -50;
+       if (right > 100)
+               right = 100;
+//printk("giova: volume put %d %d\n", __LINE__, addr);
+       //spin_lock_irq(&dummy->mixer_lock);
+       //spin_lock_irqsave(&dummy->mixer_lock, flags);
+       spin_lock_bh(&dummy->mixer_lock);
+       change = dummy->mixer_volume[addr][0] != left || dummy->mixer_volume[addr][1] != right;
+       dummy->mixer_volume[addr][0] = left;
+       dummy->mixer_volume[addr][1] = right;
+       //spin_unlock_irq(&dummy->mixer_lock);
+       //spin_unlock_irqrestore(&dummy->mixer_lock, flags);
+       spin_unlock_bh(&dummy->mixer_lock);
+       return change;
+}
+
+static const DECLARE_TLV_DB_SCALE(db_scale_dummy, -4500, 30, 0);
+
+#define DUMMY_CAPSRC(xname, xindex, addr) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
+  .info = snd_dummy_capsrc_info, \
+  .get = snd_dummy_capsrc_get, .put = snd_dummy_capsrc_put, \
+  .private_value = addr }
+
+#define snd_dummy_capsrc_info  snd_ctl_boolean_stereo_info
+
+static int snd_dummy_capsrc_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol);
+       int addr = kcontrol->private_value;
+       //unsigned long flags;
+
+       if (in_irq())
+               printk("giova: line %d we are in HARDWARE IRQ\n", __LINE__);
+       //spin_lock_irq(&dummy->mixer_lock);
+       //spin_lock_irqsave(&dummy->mixer_lock, flags);
+       spin_lock_bh(&dummy->mixer_lock);
+       ucontrol->value.integer.value[0] = dummy->capture_source[addr][0];
+       ucontrol->value.integer.value[1] = dummy->capture_source[addr][1];
+       //spin_unlock_irq(&dummy->mixer_lock);
+       //spin_unlock_irqrestore(&dummy->mixer_lock, flags);
+       spin_unlock_bh(&dummy->mixer_lock);
+//printk("giova: capsrc_get %d %d\n", __LINE__, addr);
+       return 0;
+}
+
+static int snd_dummy_capsrc_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol);
+       int change, addr = kcontrol->private_value;
+       int left, right;
+       //unsigned long flags;
+
+       if (in_irq())
+               printk("giova: line %d we are in HARDWARE IRQ\n", __LINE__);
+       left = ucontrol->value.integer.value[0] & 1;
+       right = ucontrol->value.integer.value[1] & 1;
+       //spin_lock_irq(&dummy->mixer_lock);
+       //spin_lock_irqsave(&dummy->mixer_lock, flags);
+       spin_lock_bh(&dummy->mixer_lock);
+       change = dummy->capture_source[addr][0] != left && dummy->capture_source[addr][1] != right;
+       dummy->capture_source[addr][0] = left;
+       dummy->capture_source[addr][1] = right;
+       //spin_unlock_irq(&dummy->mixer_lock);
+       //spin_unlock_irqrestore(&dummy->mixer_lock, flags);
+       spin_unlock_bh(&dummy->mixer_lock);
+//printk("giova: capsrc_put %d %d\n", __LINE__, addr);
+       return change;
+}
+
+static struct snd_kcontrol_new snd_dummy_controls[] = {
+       DUMMY_VOLUME("Master Volume", 0, MIXER_ADDR_MASTER),
+       DUMMY_CAPSRC("Master Capture Switch", 0, MIXER_ADDR_MASTER),
+       DUMMY_VOLUME("Synth Volume", 0, MIXER_ADDR_SYNTH),
+       DUMMY_CAPSRC("Synth Capture Switch", 0, MIXER_ADDR_SYNTH),
+       DUMMY_VOLUME("Line Volume", 0, MIXER_ADDR_LINE),
+       DUMMY_CAPSRC("Line Capture Switch", 0, MIXER_ADDR_LINE),
+       DUMMY_VOLUME("Mic Volume", 0, MIXER_ADDR_MIC),
+       DUMMY_CAPSRC("Mic Capture Switch", 0, MIXER_ADDR_MIC),
+       DUMMY_VOLUME("CD Volume", 0, MIXER_ADDR_CD),
+       DUMMY_CAPSRC("CD Capture Switch", 0, MIXER_ADDR_CD)
+};
+
+static int __devinit snd_card_dummy_new_mixer(struct snd_dummy *dummy)
+{
+       struct snd_card *card = dummy->card;
+       unsigned int idx;
+       int err;
+
+       //giova if (snd_BUG_ON(!dummy))
+       //giova return -EINVAL;
+       spin_lock_init(&dummy->mixer_lock);
+       strcpy(card->mixername, "Dummy Mixer");
+//printk("giova: new_mixer %d\n", __LINE__);
+       return 0;                                       //giova no mixer
+
+       for (idx = 0; idx < ARRAY_SIZE(snd_dummy_controls); idx++) {
+               err = snd_ctl_add(card, snd_ctl_new1(&snd_dummy_controls[idx], dummy));
+               if (err < 0)
+                       return err;
+       }
+       return 0;
+}
+
+static int __devinit snd_dummy_probe(struct platform_device *devptr)
+{
+       struct snd_card *card;
+       struct snd_dummy *dummy;
+       int idx, err;
+       int dev = devptr->id;
+
+       card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct snd_dummy));
+       if (card == NULL)
+               return -ENOMEM;
+
+       //giova err = snd_card_create(index[dev], id[dev], THIS_MODULE,
+       //giova sizeof(struct snd_dummy), &card);
+       //giova if (err < 0)
+       //giova return err;
+       dummy = card->private_data;
+       dummy->card = card;
+       for (idx = 0; idx < MAX_PCM_DEVICES && idx < pcm_devs[dev]; idx++) {
+               if (pcm_substreams[dev] < 1)
+                       pcm_substreams[dev] = 1;
+               if (pcm_substreams[dev] > MAX_PCM_SUBSTREAMS)
+                       pcm_substreams[dev] = MAX_PCM_SUBSTREAMS;
+               err = snd_card_dummy_pcm(dummy, idx, pcm_substreams[dev]);
+               if (err < 0)
+                       goto __nodev;
+       }
+       err = snd_card_dummy_new_mixer(dummy);
+       if (err < 0)
+               goto __nodev;
+       strcpy(card->driver, "Dummy");
+       strcpy(card->shortname, "Dummy");
+       sprintf(card->longname, "Dummy %i", dev + 1);
+
+       snd_card_set_dev(card, &devptr->dev);
+
+       err = snd_card_register(card);
+       if (err == 0) {
+               platform_set_drvdata(devptr, card);
+               return 0;
+       }
+  __nodev:
+       snd_card_free(card);
+       return err;
+}
+
+static int __devexit snd_dummy_remove(struct platform_device *devptr)
+{
+
+       del_timer(&giovatimer);
+       snd_card_free(platform_get_drvdata(devptr));
+       platform_set_drvdata(devptr, NULL);
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int snd_dummy_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct snd_card *card = platform_get_drvdata(pdev);
+       struct snd_dummy *dummy = card->private_data;
+
+       snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+       snd_pcm_suspend_all(dummy->pcm);
+       return 0;
+}
+
+static int snd_dummy_resume(struct platform_device *pdev)
+{
+       struct snd_card *card = platform_get_drvdata(pdev);
+
+       snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+       return 0;
+}
+#endif
+
+#define SND_DUMMY_DRIVER       "snd_dummy"
+
+static struct platform_driver snd_dummy_driver = {
+       .probe = snd_dummy_probe,
+       .remove = __devexit_p(snd_dummy_remove),
+#ifdef CONFIG_PM
+       .suspend = snd_dummy_suspend,
+       .resume = snd_dummy_resume,
+#endif
+       .driver = {
+                          .name = SND_DUMMY_DRIVER},
+};
+
+static void snd_dummy_unregister_all(void)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(devices); ++i)
+               platform_device_unregister(devices[i]);
+       platform_driver_unregister(&snd_dummy_driver);
+}
+
+static int __init alsa_card_dummy_init(void)
+{
+       int i, cards, err;
+
+       err = platform_driver_register(&snd_dummy_driver);
+       if (err < 0)
+               return err;
+
+       if (!giovastarted) {
+               giovastarted = 1;
+               spin_lock_init(&giovalock);
+
+               spin_lock_bh(&giovalock);
+               for (i = 0; i < MAX_PCM_SUBSTREAMS; i++) {
+
+                       if (i > MAX_PCM_SUBSTREAMS || giovaindex > MAX_PCM_SUBSTREAMS) {
+                               printk("giova, %s:%d, i=%d, giovaindex=%d \n", __FILE__, __LINE__, i, giovaindex);
+                       }
+                       giovadpcms[i].substream = NULL;
+                       giovadpcms[i].dpcm = NULL;
+                       giovadpcms[i].started = 0;
+               }
+               init_timer(&giovatimer);
+               //giovatimer.data = (unsigned long) dpcm;
+               giovatimer.data = (unsigned long) &giovadpcms;
+               giovatimer.function = snd_card_dummy_pcm_timer_function;
+               giovatimer.expires = (HZ / 100) + jiffies;
+               add_timer(&giovatimer);
+               printk("snd-dummy skypiax driver, %s:%d working on a machine with %dHZ kernel\n", __FILE__, __LINE__, HZ);
+               spin_unlock_bh(&giovalock);
+       }
+
+
+       cards = 0;
+       for (i = 0; i < SNDRV_CARDS; i++) {
+               struct platform_device *device;
+               if (!enable[i])
+                       continue;
+               device = platform_device_register_simple(SND_DUMMY_DRIVER, i, NULL, 0);
+               if (IS_ERR(device))
+                       continue;
+               if (!platform_get_drvdata(device)) {
+                       platform_device_unregister(device);
+                       continue;
+               }
+               devices[i] = device;
+               cards++;
+       }
+       if (!cards) {
+#ifdef MODULE
+               printk(KERN_ERR "Dummy soundcard not found or device busy\n");
+#endif
+               snd_dummy_unregister_all();
+               return -ENODEV;
+       }
+       return 0;
+}
+
+static void __exit alsa_card_dummy_exit(void)
+{
+       del_timer(&giovatimer);
+       snd_dummy_unregister_all();
+}
+
+module_init(alsa_card_dummy_init)
+       module_exit(alsa_card_dummy_exit)
diff --git a/src/mod/endpoints/mod_skypiax/109/mod_skypiax.c b/src/mod/endpoints/mod_skypiax/109/mod_skypiax.c
new file mode 100644 (file)
index 0000000..bd39e57
--- /dev/null
@@ -0,0 +1,2527 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II <anthmct@yahoo.com>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * This module (mod_skypiax) has been contributed by:
+ *
+ * Giovanni Maruzzelli (gmaruzz@gmail.com)
+ *
+ *
+ * Further Contributors:
+ *
+ *
+ *
+ * mod_skypiax.c -- Skype compatible Endpoint Module
+ *
+ */
+
+#include "skypiax.h"
+#define MDL_CHAT_PROTO "skype"
+#define TIMER_WRITE
+
+#ifdef WIN32
+/***************/
+// from http://www.openasthra.com/c-tidbits/gettimeofday-function-for-windows/
+
+#include <time.h>
+
+#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
+#define DELTA_EPOCH_IN_MICROSECS  11644473600000000Ui64
+#else /*  */
+#define DELTA_EPOCH_IN_MICROSECS  11644473600000000ULL
+#endif /*  */
+struct sk_timezone {
+       int tz_minuteswest;                     /* minutes W of Greenwich */
+       int tz_dsttime;                         /* type of dst correction */
+};
+int gettimeofday(struct timeval *tv, struct sk_timezone *tz)
+{
+       FILETIME ft;
+       unsigned __int64 tmpres = 0;
+       static int tzflag;
+       if (NULL != tv) {
+               GetSystemTimeAsFileTime(&ft);
+               tmpres |= ft.dwHighDateTime;
+               tmpres <<= 32;
+               tmpres |= ft.dwLowDateTime;
+
+               /*converting file time to unix epoch */
+               tmpres /= 10;                   /*convert into microseconds */
+               tmpres -= DELTA_EPOCH_IN_MICROSECS;
+               tv->tv_sec = (long) (tmpres / 1000000UL);
+               tv->tv_usec = (long) (tmpres % 1000000UL);
+       }
+       if (NULL != tz) {
+               if (!tzflag) {
+                       _tzset();
+                       tzflag++;
+               }
+               tz->tz_minuteswest = _timezone / 60;
+               tz->tz_dsttime = _daylight;
+       }
+       return 0;
+}
+
+/***************/
+#endif /* WIN32 */
+SWITCH_MODULE_LOAD_FUNCTION(mod_skypiax_load);
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_skypiax_shutdown);
+SWITCH_MODULE_DEFINITION(mod_skypiax, mod_skypiax_load, mod_skypiax_shutdown, NULL);
+SWITCH_STANDARD_API(sk_function);
+/* BEGIN: Changes here */
+#define SK_SYNTAX "list [full] || console || skype_API_msg || remove < skypeusername | #interface_name | #interface_id > || reload"
+/* END: Changes heres */
+SWITCH_STANDARD_API(skypiax_function);
+#define SKYPIAX_SYNTAX "interface_name skype_API_msg"
+
+SWITCH_STANDARD_API(skypiax_chat_function);
+#define SKYPIAX_CHAT_SYNTAX "interface_name remote_skypename TEXT"
+/* BEGIN: Changes here */
+#define FULL_RELOAD 0
+#define SOFT_RELOAD 1
+/* END: Changes heres */
+
+char *interface_status[] = {   /* should match SKYPIAX_STATE_xxx in skypiax.h */
+       "IDLE",
+       "DOWN",
+       "RING",
+       "DIALING",
+       "BUSY",
+       "UP",
+       "RINGING",
+       "PRERING",
+       "DOUBLE",
+       "SELECTD",
+       "HANG_RQ",
+       "PREANSW"
+};
+char *skype_callflow[] = {             /* should match CALLFLOW_XXX in skypiax.h */
+       "CALL_IDLE",
+       "CALL_DOWN",
+       "INCOMING_RNG",
+       "CALL_DIALING",
+       "CALL_LINEBUSY",
+       "CALL_ACTIVE",
+       "INCOMING_HNG",
+       "CALL_RLEASD",
+       "CALL_NOCARR",
+       "CALL_INFLUX",
+       "CALL_INCOMING",
+       "CALL_FAILED",
+       "CALL_NOSRVC",
+       "CALL_OUTRESTR",
+       "CALL_SECFAIL",
+       "CALL_NOANSWER",
+       "STATUS_FNSHED",
+       "STATUS_CANCLED",
+       "STATUS_FAILED",
+       "STATUS_REFUSED",
+       "STATUS_RINGING",
+       "STATUS_INPROGRS",
+       "STATUS_UNPLACD",
+       "STATUS_ROUTING",
+       "STATUS_EARLYMD",
+       "INCOMING_CLID",
+       "STATUS_RMTEHOLD"
+};
+
+
+static struct {
+       int debug;
+       char *ip;
+       int port;
+       char *dialplan;
+       char *destination;
+       char *context;
+       char *codec_string;
+       char *codec_order[SWITCH_MAX_CODECS];
+       int codec_order_last;
+       char *codec_rates_string;
+       char *codec_rates[SWITCH_MAX_CODECS];
+       int codec_rates_last;
+       unsigned int flags;
+       int fd;
+       int calls;
+       int real_interfaces;
+       int next_interface;
+       char hold_music[256];
+       private_t SKYPIAX_INTERFACES[SKYPIAX_MAX_INTERFACES];
+       switch_mutex_t *mutex;
+       private_t *sk_console;
+} globals;
+
+switch_endpoint_interface_t *skypiax_endpoint_interface;
+switch_memory_pool_t *skypiax_module_pool = NULL;
+int running = 0;
+
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_context, globals.context);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_destination, globals.destination);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_codec_string, globals.codec_string);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_codec_rates_string, globals.codec_rates_string);
+
+/* BEGIN: Changes here */
+static switch_status_t interface_exists(char *the_interface);
+static switch_status_t remove_interface(char *the_interface);
+/* END: Changes here */
+
+static switch_status_t channel_on_init(switch_core_session_t *session);
+static switch_status_t channel_on_hangup(switch_core_session_t *session);
+static switch_status_t channel_on_destroy(switch_core_session_t *session);
+static switch_status_t channel_on_routing(switch_core_session_t *session);
+static switch_status_t channel_on_exchange_media(switch_core_session_t *session);
+static switch_status_t channel_on_consume_media(switch_core_session_t *session);
+static switch_status_t channel_on_soft_execute(switch_core_session_t *session);
+static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session,
+                                                                                                       switch_event_t *var_event,
+                                                                                                       switch_caller_profile_t *outbound_profile,
+                                                                                                       switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
+                                                                                                       switch_call_cause_t *cancel_cause);
+static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id);
+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);
+static switch_status_t skypiax_tech_init(private_t * tech_pvt, switch_core_session_t *session);
+
+static switch_status_t skypiax_codec(private_t * tech_pvt, int sample_rate, int codec_ms)
+{
+       switch_core_session_t *session = NULL;
+
+       if (switch_core_codec_init
+               (&tech_pvt->read_codec, "L16", NULL, sample_rate, codec_ms, 1,
+                SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, NULL) != SWITCH_STATUS_SUCCESS) {
+               ERRORA("Can't load codec?\n", SKYPIAX_P_LOG);
+               return SWITCH_STATUS_FALSE;
+       }
+
+       if (switch_core_codec_init
+               (&tech_pvt->write_codec, "L16", NULL, sample_rate, codec_ms, 1,
+                SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, NULL) != SWITCH_STATUS_SUCCESS) {
+               ERRORA("Can't load codec?\n", SKYPIAX_P_LOG);
+               switch_core_codec_destroy(&tech_pvt->read_codec);
+               return SWITCH_STATUS_FALSE;
+       }
+
+       tech_pvt->read_frame.rate = sample_rate;
+       tech_pvt->read_frame.codec = &tech_pvt->read_codec;
+
+       session = switch_core_session_locate(tech_pvt->session_uuid_str);
+
+       if (session) {
+               switch_core_session_set_read_codec(session, &tech_pvt->read_codec);
+               switch_core_session_set_write_codec(session, &tech_pvt->write_codec);
+               switch_core_session_rwunlock(session);
+       } else {
+               ERRORA("no session\n", SKYPIAX_P_LOG);
+               return SWITCH_STATUS_FALSE;
+       }
+
+       return SWITCH_STATUS_SUCCESS;
+
+}
+
+switch_status_t skypiax_tech_init(private_t * tech_pvt, switch_core_session_t *session)
+{
+
+       switch_assert(tech_pvt != NULL);
+       switch_assert(session != NULL);
+       tech_pvt->read_frame.data = tech_pvt->databuf;
+       tech_pvt->read_frame.buflen = sizeof(tech_pvt->databuf);
+       switch_mutex_init(&tech_pvt->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
+       switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
+       switch_core_session_set_private(session, tech_pvt);
+       switch_copy_string(tech_pvt->session_uuid_str, switch_core_session_get_uuid(session), sizeof(tech_pvt->session_uuid_str));
+       if (!strlen(tech_pvt->session_uuid_str)) {
+               ERRORA("no tech_pvt->session_uuid_str\n", SKYPIAX_P_LOG);
+               return SWITCH_STATUS_FALSE;
+       }
+       if (skypiax_codec(tech_pvt, SAMPLERATE_SKYPIAX, 20) != SWITCH_STATUS_SUCCESS) {
+               ERRORA("skypiax_codec FAILED\n", SKYPIAX_P_LOG);
+               return SWITCH_STATUS_FALSE;
+       }
+
+       if (switch_core_timer_init(&tech_pvt->timer_read, "soft", 20, tech_pvt->read_codec.implementation->samples_per_packet, skypiax_module_pool) !=
+               SWITCH_STATUS_SUCCESS) {
+               ERRORA("setup timer failed\n", SKYPIAX_P_LOG);
+               return SWITCH_STATUS_FALSE;
+       }
+
+       switch_core_timer_sync(&tech_pvt->timer_read);
+
+#ifdef TIMER_WRITE
+       if (switch_core_timer_init(&tech_pvt->timer_write, "soft", 20, tech_pvt->write_codec.implementation->samples_per_packet, skypiax_module_pool) !=
+               SWITCH_STATUS_SUCCESS) {
+               ERRORA("setup timer failed\n", SKYPIAX_P_LOG);
+               return SWITCH_STATUS_FALSE;
+       }
+
+       switch_core_timer_sync(&tech_pvt->timer_write);
+#endif // TIMER_WRITE
+
+       DEBUGA_SKYPE("skypiax_tech_init SUCCESS\n", SKYPIAX_P_LOG);
+       return SWITCH_STATUS_SUCCESS;
+}
+
+/* BEGIN: Changes here */
+static switch_status_t interface_exists(char *the_interface)
+{
+       int i;
+       int interface_id;
+
+       if (*the_interface == '#') {    /* look by interface id or interface name */
+               the_interface++;
+               switch_assert(the_interface);
+               interface_id = atoi(the_interface);
+
+               /* take a number as interface id */
+               if (interface_id > 0 || (interface_id == 0 && strcmp(the_interface, "0") == 0)) {
+                       if (strlen(globals.SKYPIAX_INTERFACES[interface_id].name)) {
+                               return SWITCH_STATUS_SUCCESS;
+                       }
+               } else {
+                       /* interface name */
+                       for (interface_id = 0; interface_id < SKYPIAX_MAX_INTERFACES; interface_id++) {
+                               if (strcmp(globals.SKYPIAX_INTERFACES[interface_id].name, the_interface) == 0) {
+                                       return SWITCH_STATUS_SUCCESS;
+                                       break;
+                               }
+                       }
+               }
+       } else {                                        /* look by skype_user */
+
+
+               for (i = 0; i < SKYPIAX_MAX_INTERFACES; i++) {
+                       if (strlen(globals.SKYPIAX_INTERFACES[i].skype_user)) {
+                               if (strcmp(globals.SKYPIAX_INTERFACES[i].skype_user, the_interface) == 0) {
+                                       return SWITCH_STATUS_SUCCESS;
+                               }
+                       }
+               }
+       }
+       return SWITCH_STATUS_FALSE;
+}
+
+static switch_status_t remove_interface(char *the_interface)
+{
+       int x = 10;
+       unsigned int howmany = 8;
+       int interface_id = -1;
+       private_t *tech_pvt = NULL;
+       switch_status_t status;
+
+       //running = 0;
+
+
+       if (*the_interface == '#') {    /* remove by interface id or interface name */
+               the_interface++;
+               switch_assert(the_interface);
+               interface_id = atoi(the_interface);
+
+               if (interface_id > 0 || (interface_id == 0 && strcmp(the_interface, "0") == 0)) {
+                       /* take a number as interface id */
+                       tech_pvt = &globals.SKYPIAX_INTERFACES[interface_id];
+               } else {
+
+                       for (interface_id = 0; interface_id < SKYPIAX_MAX_INTERFACES; interface_id++) {
+                               if (strcmp(globals.SKYPIAX_INTERFACES[interface_id].name, the_interface) == 0) {
+                                       tech_pvt = &globals.SKYPIAX_INTERFACES[interface_id];
+                                       break;
+                               }
+                       }
+               }
+       } else {                                        /* remove by skype_user */
+               for (interface_id = 0; interface_id < SKYPIAX_MAX_INTERFACES; interface_id++) {
+                       if (strcmp(globals.SKYPIAX_INTERFACES[interface_id].skype_user, the_interface) == 0) {
+                               tech_pvt = &globals.SKYPIAX_INTERFACES[interface_id];
+                               break;
+                       }
+               }
+       }
+
+       if (!tech_pvt) {
+               DEBUGA_SKYPE("interface '%s' does not exist\n", SKYPIAX_P_LOG, the_interface);
+               goto end;
+       }
+
+       if (strlen(globals.SKYPIAX_INTERFACES[interface_id].session_uuid_str)) {
+               DEBUGA_SKYPE("interface '%s' is busy\n", SKYPIAX_P_LOG, the_interface);
+               goto end;
+       }
+
+       globals.SKYPIAX_INTERFACES[interface_id].running = 0;
+
+       if (globals.SKYPIAX_INTERFACES[interface_id].skypiax_signaling_thread) {
+#ifdef WIN32
+               switch_file_write(tech_pvt->SkypiaxHandles.fdesc[1], "sciutati", &howmany);     // let's the controldev_thread die
+#else /* WIN32 */
+               howmany = write(tech_pvt->SkypiaxHandles.fdesc[1], "sciutati", howmany);
+#endif /* WIN32 */
+       }
+
+       if (globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread) {
+#ifdef WIN32
+               if (SendMessage(tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle, WM_DESTROY, 0, 0) == FALSE) {    // let's the skypiax_api_thread_func die
+                       DEBUGA_SKYPE("got FALSE here, thread probably was already dead. GetLastError returned: %d\n", SKYPIAX_P_LOG, GetLastError());
+                       globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread = NULL;
+               }
+#else
+               if (tech_pvt->running && tech_pvt->SkypiaxHandles.disp) {
+                       XEvent e;
+                       Atom atom1 = XInternAtom(tech_pvt->SkypiaxHandles.disp, "SKYPECONTROLAPI_MESSAGE_BEGIN", False);
+                       memset(&e, 0, sizeof(e));
+                       e.xclient.type = ClientMessage;
+                       e.xclient.message_type = atom1; /*  leading message */
+                       e.xclient.display = tech_pvt->SkypiaxHandles.disp;
+                       e.xclient.window = tech_pvt->SkypiaxHandles.skype_win;
+                       e.xclient.format = 8;
+
+                       XSendEvent(tech_pvt->SkypiaxHandles.disp, tech_pvt->SkypiaxHandles.win, False, 0, &e);
+                       XSync(tech_pvt->SkypiaxHandles.disp, False);
+               }
+#endif
+       }
+
+       while (x) {
+               x--;
+               switch_yield(50000);
+       }
+
+       if (globals.SKYPIAX_INTERFACES[interface_id].skypiax_signaling_thread) {
+               switch_thread_join(&status, globals.SKYPIAX_INTERFACES[interface_id].skypiax_signaling_thread);
+       }
+
+       if (globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread) {
+               switch_thread_join(&status, globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread);
+       }
+
+       switch_mutex_lock(globals.mutex);
+       if (globals.sk_console == &globals.SKYPIAX_INTERFACES[interface_id]) {
+               DEBUGA_SKYPE("interface '%s' no more console\n", SKYPIAX_P_LOG, the_interface);
+               globals.sk_console = NULL;
+       } else {
+               DEBUGA_SKYPE("interface '%s' STILL console\n", SKYPIAX_P_LOG, the_interface);
+       }
+       memset(&globals.SKYPIAX_INTERFACES[interface_id], '\0', sizeof(private_t));
+       globals.real_interfaces--;
+       switch_mutex_unlock(globals.mutex);
+
+       DEBUGA_SKYPE("interface '%s' deleted successfully\n", SKYPIAX_P_LOG, the_interface);
+       globals.SKYPIAX_INTERFACES[interface_id].running = 1;
+  end:
+       //running = 1;
+       return SWITCH_STATUS_SUCCESS;
+}
+
+/* END: Changes here */
+
+/* 
+   State methods they get called when the state changes to the specific state 
+   returning SWITCH_STATUS_SUCCESS tells the core to execute the standard state method next
+   so if you fully implement the state you can return SWITCH_STATUS_FALSE to skip it.
+*/
+static switch_status_t channel_on_init(switch_core_session_t *session)
+{
+       switch_channel_t *channel;
+       private_t *tech_pvt = NULL;
+
+       tech_pvt = switch_core_session_get_private(session);
+       switch_assert(tech_pvt != NULL);
+
+       channel = switch_core_session_get_channel(session);
+       switch_assert(channel != NULL);
+       //ERRORA("%s CHANNEL INIT\n", SKYPIAX_P_LOG, tech_pvt->name);
+       switch_set_flag(tech_pvt, TFLAG_IO);
+
+       /* Move channel's state machine to ROUTING. This means the call is trying
+          to get from the initial start where the call because, to the point
+          where a destination has been identified. If the channel is simply
+          left in the initial state, nothing will happen. */
+       switch_channel_set_state(channel, CS_ROUTING);
+       switch_mutex_lock(globals.mutex);
+       globals.calls++;
+
+       switch_mutex_unlock(globals.mutex);
+       DEBUGA_SKYPE("%s CHANNEL INIT %s\n", SKYPIAX_P_LOG, tech_pvt->name, switch_core_session_get_uuid(session));
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_on_destroy(switch_core_session_t *session)
+{
+       private_t *tech_pvt = NULL;
+
+       tech_pvt = switch_core_session_get_private(session);
+
+
+       if (tech_pvt) {
+               DEBUGA_SKYPE("%s CHANNEL DESTROY %s\n", SKYPIAX_P_LOG, tech_pvt->name, switch_core_session_get_uuid(session));
+
+               if (switch_core_codec_ready(&tech_pvt->read_codec)) {
+                       switch_core_codec_destroy(&tech_pvt->read_codec);
+               }
+
+               if (switch_core_codec_ready(&tech_pvt->write_codec)) {
+                       switch_core_codec_destroy(&tech_pvt->write_codec);
+               }
+
+               switch_core_timer_destroy(&tech_pvt->timer_read);
+#ifdef TIMER_WRITE
+
+               switch_core_timer_destroy(&tech_pvt->timer_write);
+#endif // TIMER_WRITE
+
+
+               *tech_pvt->session_uuid_str = '\0';
+               tech_pvt->interface_state = SKYPIAX_STATE_IDLE;
+               if (tech_pvt->skype_callflow == CALLFLOW_STATUS_FINISHED) {
+                       tech_pvt->skype_callflow = CALLFLOW_CALL_IDLE;
+               }
+               switch_core_session_set_private(session, NULL);
+       } else {
+               DEBUGA_SKYPE("!!!!!!NO tech_pvt!!!! CHANNEL DESTROY %s\n", SKYPIAX_P_LOG, switch_core_session_get_uuid(session));
+       }
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_on_hangup(switch_core_session_t *session)
+{
+       switch_channel_t *channel = NULL;
+       private_t *tech_pvt = NULL;
+       char msg_to_skype[256];
+
+
+       channel = switch_core_session_get_channel(session);
+       switch_assert(channel != NULL);
+
+       tech_pvt = switch_core_session_get_private(session);
+       switch_assert(tech_pvt != NULL);
+
+       if (!switch_channel_test_flag(channel, CF_ANSWERED)) {
+               if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
+                       tech_pvt->ob_failed_calls++;
+               } else {
+                       tech_pvt->ib_failed_calls++;
+               }
+       }
+
+       switch_clear_flag(tech_pvt, TFLAG_IO);
+       switch_clear_flag(tech_pvt, TFLAG_VOICE);
+       //switch_set_flag(tech_pvt, TFLAG_HANGUP);
+
+       if (strlen(tech_pvt->skype_call_id)) {
+               //switch_thread_cond_signal(tech_pvt->cond);
+               DEBUGA_SKYPE("hanging up skype call: %s\n", SKYPIAX_P_LOG, tech_pvt->skype_call_id);
+               sprintf(msg_to_skype, "ALTER CALL %s HANGUP", tech_pvt->skype_call_id);
+               skypiax_signaling_write(tech_pvt, msg_to_skype);
+       }
+       //memset(tech_pvt->session_uuid_str, '\0', sizeof(tech_pvt->session_uuid_str));
+       //*tech_pvt->session_uuid_str = '\0';
+       DEBUGA_SKYPE("%s CHANNEL HANGUP\n", SKYPIAX_P_LOG, tech_pvt->name);
+       switch_mutex_lock(globals.mutex);
+       globals.calls--;
+       if (globals.calls < 0) {
+               globals.calls = 0;
+       }
+
+       tech_pvt->interface_state = SKYPIAX_STATE_IDLE;
+       if (tech_pvt->skype_callflow == CALLFLOW_STATUS_FINISHED) {
+               tech_pvt->skype_callflow = CALLFLOW_CALL_IDLE;
+       }
+       switch_mutex_unlock(globals.mutex);
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_on_routing(switch_core_session_t *session)
+{
+       switch_channel_t *channel = NULL;
+       private_t *tech_pvt = NULL;
+
+       channel = switch_core_session_get_channel(session);
+       switch_assert(channel != NULL);
+
+       tech_pvt = switch_core_session_get_private(session);
+       switch_assert(tech_pvt != NULL);
+
+       DEBUGA_SKYPE("%s CHANNEL ROUTING\n", SKYPIAX_P_LOG, tech_pvt->name);
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_on_execute(switch_core_session_t *session)
+{
+
+       switch_channel_t *channel = NULL;
+       private_t *tech_pvt = NULL;
+
+       channel = switch_core_session_get_channel(session);
+       switch_assert(channel != NULL);
+
+       tech_pvt = switch_core_session_get_private(session);
+       switch_assert(tech_pvt != NULL);
+
+       DEBUGA_SKYPE("%s CHANNEL EXECUTE\n", SKYPIAX_P_LOG, tech_pvt->name);
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig)
+{
+       switch_channel_t *channel = NULL;
+       private_t *tech_pvt = NULL;
+
+       channel = switch_core_session_get_channel(session);
+       switch_assert(channel != NULL);
+
+       tech_pvt = switch_core_session_get_private(session);
+       switch_assert(tech_pvt != NULL);
+
+       DEBUGA_SKYPE("%s CHANNEL KILL_CHANNEL\n", SKYPIAX_P_LOG, tech_pvt->name);
+       switch (sig) {
+       case SWITCH_SIG_KILL:
+               DEBUGA_SKYPE("%s CHANNEL got SWITCH_SIG_KILL\n", SKYPIAX_P_LOG, switch_channel_get_name(channel));
+               switch_mutex_lock(tech_pvt->flag_mutex);
+               switch_clear_flag(tech_pvt, TFLAG_IO);
+               switch_clear_flag(tech_pvt, TFLAG_VOICE);
+               switch_set_flag(tech_pvt, TFLAG_HANGUP);
+               if (tech_pvt->skype_callflow == CALLFLOW_STATUS_REMOTEHOLD) {
+                       ERRORA("FYI %s CHANNEL in CALLFLOW_STATUS_REMOTEHOLD got SWITCH_SIG_KILL\n", SKYPIAX_P_LOG, switch_channel_get_name(channel));
+                       channel_on_hangup(session);
+               }
+               if (switch_channel_get_state(channel) == CS_NEW) {
+                       ERRORA("FYI %s CHANNEL in CS_NEW state got SWITCH_SIG_KILL\n", SKYPIAX_P_LOG, switch_channel_get_name(channel));
+                       channel_on_hangup(session);
+               }
+               if (switch_channel_get_state(channel) != CS_NEW && switch_channel_get_state(channel) < CS_EXECUTE) {
+                       ERRORA("FYI %s CHANNEL in %d state got SWITCH_SIG_KILL\n", SKYPIAX_P_LOG, switch_channel_get_name(channel), switch_channel_get_state(channel));
+                       channel_on_hangup(session);
+               }
+               switch_mutex_unlock(tech_pvt->flag_mutex);
+               break;
+       case SWITCH_SIG_BREAK:
+               DEBUGA_SKYPE("%s CHANNEL got SWITCH_SIG_BREAK\n", SKYPIAX_P_LOG, switch_channel_get_name(channel));
+               //switch_set_flag(tech_pvt, TFLAG_BREAK);
+               switch_mutex_lock(tech_pvt->flag_mutex);
+               switch_set_flag(tech_pvt, TFLAG_BREAK);
+               switch_mutex_unlock(tech_pvt->flag_mutex);
+               break;
+       default:
+               break;
+       }
+
+       return SWITCH_STATUS_SUCCESS;
+}
+static switch_status_t channel_on_consume_media(switch_core_session_t *session)
+{
+       private_t *tech_pvt = NULL;
+
+       tech_pvt = switch_core_session_get_private(session);
+
+       DEBUGA_SKYPE("%s CHANNEL CONSUME_MEDIA\n", SKYPIAX_P_LOG, tech_pvt->name);
+       return SWITCH_STATUS_SUCCESS;
+}
+
+
+static switch_status_t channel_on_exchange_media(switch_core_session_t *session)
+{
+       private_t *tech_pvt = NULL;
+       tech_pvt = switch_core_session_get_private(session);
+       DEBUGA_SKYPE("%s CHANNEL EXCHANGE_MEDIA\n", SKYPIAX_P_LOG, tech_pvt->name);
+       return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_on_soft_execute(switch_core_session_t *session)
+{
+       private_t *tech_pvt = NULL;
+       tech_pvt = switch_core_session_get_private(session);
+       DEBUGA_SKYPE("%s CHANNEL SOFT_EXECUTE\n", SKYPIAX_P_LOG, tech_pvt->name);
+       return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)
+{
+       private_t *tech_pvt = switch_core_session_get_private(session);
+       switch_assert(tech_pvt != NULL);
+
+       DEBUGA_SKYPE("%s CHANNEL SEND_DTMF\n", SKYPIAX_P_LOG, tech_pvt->name);
+       DEBUGA_SKYPE("DTMF: %c\n", SKYPIAX_P_LOG, dtmf->digit);
+
+       skypiax_senddigit(tech_pvt, dtmf->digit);
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
+{
+       switch_channel_t *channel = NULL;
+       private_t *tech_pvt = NULL;
+       switch_byte_t *data;
+
+       channel = switch_core_session_get_channel(session);
+       switch_assert(channel != NULL);
+
+       tech_pvt = switch_core_session_get_private(session);
+       switch_assert(tech_pvt != NULL);
+
+       if (!switch_channel_ready(channel) || !switch_test_flag(tech_pvt, TFLAG_IO)) {
+               ERRORA("channel not ready \n", SKYPIAX_P_LOG);
+               //TODO: kill the bastard
+               return SWITCH_STATUS_FALSE;
+       }
+
+       tech_pvt->read_frame.flags = SFF_NONE;
+       *frame = NULL;
+
+       //switch_core_timer_next(&tech_pvt->timer_read);
+
+       if (!skypiax_audio_read(tech_pvt)) {
+
+               ERRORA("skypiax_audio_read ERROR\n", SKYPIAX_P_LOG);
+
+       } else {
+               switch_set_flag(tech_pvt, TFLAG_VOICE);
+       }
+
+       while (switch_test_flag(tech_pvt, TFLAG_IO)) {
+               if (switch_test_flag(tech_pvt, TFLAG_BREAK)) {
+                       switch_clear_flag(tech_pvt, TFLAG_BREAK);
+                       DEBUGA_SKYPE("CHANNEL READ FRAME goto CNG\n", SKYPIAX_P_LOG);
+                       goto cng;
+               }
+
+               if (!switch_test_flag(tech_pvt, TFLAG_IO)) {
+                       DEBUGA_SKYPE("CHANNEL READ FRAME not IO\n", SKYPIAX_P_LOG);
+                       return SWITCH_STATUS_FALSE;
+               }
+
+               if (switch_test_flag(tech_pvt, TFLAG_IO) && switch_test_flag(tech_pvt, TFLAG_VOICE)) {
+                       switch_clear_flag(tech_pvt, TFLAG_VOICE);
+                       if (!tech_pvt->read_frame.datalen) {
+                               DEBUGA_SKYPE("CHANNEL READ CONTINUE\n", SKYPIAX_P_LOG);
+                               continue;
+                       }
+                       *frame = &tech_pvt->read_frame;
+#if SWITCH_BYTE_ORDER == __BIG_ENDIAN
+                       if (switch_test_flag(tech_pvt, TFLAG_LINEAR)) {
+                               switch_swap_linear((*frame)->data, (int) (*frame)->datalen / 2);
+                       }
+#endif
+                       return SWITCH_STATUS_SUCCESS;
+               }
+
+               DEBUGA_SKYPE("CHANNEL READ no TFLAG_IO\n", SKYPIAX_P_LOG);
+               return SWITCH_STATUS_FALSE;
+
+       }
+
+       DEBUGA_SKYPE("CHANNEL READ FALSE\n", SKYPIAX_P_LOG);
+       return SWITCH_STATUS_FALSE;
+
+  cng:
+       data = (switch_byte_t *) tech_pvt->read_frame.data;
+       data[0] = 65;
+       data[1] = 0;
+       tech_pvt->read_frame.datalen = 2;
+       tech_pvt->read_frame.flags = SFF_CNG;
+       *frame = &tech_pvt->read_frame;
+       return SWITCH_STATUS_SUCCESS;
+
+}
+
+static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
+{
+       switch_channel_t *channel = NULL;
+       private_t *tech_pvt = NULL;
+       unsigned int sent;
+
+       channel = switch_core_session_get_channel(session);
+       switch_assert(channel != NULL);
+
+       tech_pvt = switch_core_session_get_private(session);
+       switch_assert(tech_pvt != NULL);
+
+       if (!switch_channel_ready(channel) || !switch_test_flag(tech_pvt, TFLAG_IO)) {
+               ERRORA("channel not ready \n", SKYPIAX_P_LOG);
+               //TODO: kill the bastard
+               return SWITCH_STATUS_FALSE;
+       }
+#if SWITCH_BYTE_ORDER == __BIG_ENDIAN
+       if (switch_test_flag(tech_pvt, TFLAG_LINEAR)) {
+               switch_swap_linear(frame->data, (int) frame->datalen / 2);
+       }
+#endif
+
+       sent = frame->datalen;
+#ifdef WIN32
+       //switch_file_write(tech_pvt->audiopipe_cli[1], frame->data, &sent);
+#else /* WIN32 */
+       //sent = write(tech_pvt->audiopipe_cli[1], frame->data, sent);
+#endif /* WIN32 */
+       if (tech_pvt->flag_audio_cli == 1) {
+               switch_sleep(1000);             //1 millisec
+       }
+       if (tech_pvt->flag_audio_cli == 0) {
+#ifdef TIMER_WRITE
+               switch_core_timer_next(&tech_pvt->timer_write);
+#endif // TIMER_WRITE
+
+               memcpy(tech_pvt->audiobuf_cli, frame->data, frame->datalen);
+               tech_pvt->flag_audio_cli = 1;
+       }
+       //NOTICA("write \n", SKYPIAX_P_LOG);
+
+       if (sent != frame->datalen && sent != -1) {
+               DEBUGA_SKYPE("CLI PIPE write %d\n", SKYPIAX_P_LOG, sent);
+       }
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_answer_channel(switch_core_session_t *session)
+{
+       private_t *tech_pvt;
+       switch_channel_t *channel = NULL;
+
+       channel = switch_core_session_get_channel(session);
+       switch_assert(channel != NULL);
+
+       tech_pvt = switch_core_session_get_private(session);
+       switch_assert(tech_pvt != NULL);
+
+       DEBUGA_SKYPE("ANSWERED! \n", SKYPIAX_P_LOG);
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg)
+{
+       switch_channel_t *channel;
+       private_t *tech_pvt;
+       //int i;
+
+       channel = switch_core_session_get_channel(session);
+       switch_assert(channel != NULL);
+
+       tech_pvt = (private_t *) switch_core_session_get_private(session);
+       switch_assert(tech_pvt != NULL);
+
+       switch (msg->message_id) {
+       case SWITCH_MESSAGE_INDICATE_ANSWER:
+               {
+                       DEBUGA_SKYPE("MSG_ID=%d, TO BE ANSWERED!\n", SKYPIAX_P_LOG, msg->message_id);
+
+                       switch_core_timer_sync(&tech_pvt->timer_read);
+#ifdef TIMER_WRITE
+                       switch_core_timer_sync(&tech_pvt->timer_write);
+#endif // TIMER_WRITE
+                       channel_answer_channel(session);
+               }
+               break;
+       case SWITCH_MESSAGE_INDICATE_AUDIO_SYNC:
+
+               DEBUGA_SKYPE("%s CHANNEL got SWITCH_MESSAGE_INDICATE_AUDIO_SYNC\n", SKYPIAX_P_LOG, switch_channel_get_name(channel));
+
+               switch_core_timer_sync(&tech_pvt->timer_read);
+#ifdef TIMER_WRITE
+               switch_core_timer_sync(&tech_pvt->timer_write);
+#endif // TIMER_WRITE
+               break;
+       default:
+               {
+
+                       switch_core_timer_sync(&tech_pvt->timer_read);
+#ifdef TIMER_WRITE
+
+                       switch_core_timer_sync(&tech_pvt->timer_write);
+#endif // TIMER_WRITE
+
+                       DEBUGA_SKYPE("MSG_ID=%d\n", SKYPIAX_P_LOG, msg->message_id);
+               }
+               break;
+       }
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_receive_event(switch_core_session_t *session, switch_event_t *event)
+{
+       struct private_object *tech_pvt = switch_core_session_get_private(session);
+       char *body = switch_event_get_body(event);
+       switch_assert(tech_pvt != NULL);
+
+       if (!body) {
+               body = "";
+       }
+
+       WARNINGA("event: |||%s|||\n", SKYPIAX_P_LOG, body);
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
+switch_state_handler_table_t skypiax_state_handlers = {
+       /*.on_init */ channel_on_init,
+       /*.on_routing */ channel_on_routing,
+       /*.on_execute */ channel_on_execute,
+       /*.on_hangup */ channel_on_hangup,
+       /*.on_exchange_media */ channel_on_exchange_media,
+       /*.on_soft_execute */ channel_on_soft_execute,
+       /*.on_consume_media */ channel_on_consume_media,
+       /*.on_hibernate */ NULL,
+       /*.on_reset */ NULL,
+       /*.on_park */ NULL,
+       /*.on_reporting */ NULL,
+       /*.on_destroy */ channel_on_destroy
+};
+
+switch_io_routines_t skypiax_io_routines = {
+       /*.outgoing_channel */ channel_outgoing_channel,
+       /*.read_frame */ channel_read_frame,
+       /*.write_frame */ channel_write_frame,
+       /*.kill_channel */ channel_kill_channel,
+       /*.send_dtmf */ channel_send_dtmf,
+       /*.receive_message */ channel_receive_message,
+       /*.receive_event */ channel_receive_event
+};
+
+static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session,
+                                                                                                       switch_event_t *var_event,
+                                                                                                       switch_caller_profile_t *outbound_profile,
+                                                                                                       switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
+                                                                                                       switch_call_cause_t *cancel_cause)
+{
+       private_t *tech_pvt = NULL;
+       if ((*new_session = switch_core_session_request(skypiax_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, pool)) != 0) {
+               switch_channel_t *channel = NULL;
+               switch_caller_profile_t *caller_profile;
+               char *rdest;
+               int found = 0;
+               char interface_name[256];
+
+               DEBUGA_SKYPE("1 SESSION_REQUEST %s\n", SKYPIAX_P_LOG, switch_core_session_get_uuid(*new_session));
+               switch_core_session_add_stream(*new_session, NULL);
+
+
+               if (!zstr(outbound_profile->destination_number)) {
+                       int i;
+                       char *slash;
+
+                       switch_copy_string(interface_name, outbound_profile->destination_number, 255);
+                       slash = strrchr(interface_name, '/');
+                       *slash = '\0';
+
+                       switch_mutex_lock(globals.mutex);
+                       if (strncmp("ANY", interface_name, strlen(interface_name)) == 0 || strncmp("RR", interface_name, strlen(interface_name)) == 0) {
+                               /* we've been asked for the "ANY" interface, let's find the first idle interface */
+                               //DEBUGA_SKYPE("Finding one available skype interface\n", SKYPIAX_P_LOG);
+                               //tech_pvt = find_available_skypiax_interface(NULL);
+                               //if (tech_pvt)
+                               //found = 1;
+                               //} else if (strncmp("RR", interface_name, strlen(interface_name)) == 0) {
+                               /* Find the first idle interface using Round Robin */
+                               DEBUGA_SKYPE("Finding one available skype interface RR\n", SKYPIAX_P_LOG);
+                               tech_pvt = find_available_skypiax_interface_rr(NULL);
+                               if (tech_pvt)
+                                       found = 1;
+                       }
+
+                       for (i = 0; !found && i < SKYPIAX_MAX_INTERFACES; i++) {
+                               /* we've been asked for a normal interface name, or we have not found idle interfaces to serve as the "ANY" interface */
+                               if (strlen(globals.SKYPIAX_INTERFACES[i].name)
+                                       && (strncmp(globals.SKYPIAX_INTERFACES[i].name, interface_name, strlen(interface_name)) == 0)) {
+                                       if (strlen(globals.SKYPIAX_INTERFACES[i].session_uuid_str)) {
+                                               DEBUGA_SKYPE
+                                                       ("globals.SKYPIAX_INTERFACES[%d].name=|||%s||| session_uuid_str=|||%s||| is BUSY\n",
+                                                        SKYPIAX_P_LOG, i, globals.SKYPIAX_INTERFACES[i].name, globals.SKYPIAX_INTERFACES[i].session_uuid_str);
+                                               DEBUGA_SKYPE("1 SESSION_DESTROY %s\n", SKYPIAX_P_LOG, switch_core_session_get_uuid(*new_session));
+                                               switch_core_session_destroy(new_session);
+                                               switch_mutex_unlock(globals.mutex);
+                                               return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+                                       }
+
+                                       DEBUGA_SKYPE("globals.SKYPIAX_INTERFACES[%d].name=|||%s|||?\n", SKYPIAX_P_LOG, i, globals.SKYPIAX_INTERFACES[i].name);
+                                       tech_pvt = &globals.SKYPIAX_INTERFACES[i];
+                                       found = 1;
+                                       break;
+                               }
+
+                       }
+
+               } else {
+                       ERRORA("Doh! no destination number?\n", SKYPIAX_P_LOG);
+                       switch_core_session_destroy(new_session);
+                       return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+               }
+
+               if (!found) {
+                       DEBUGA_SKYPE("Doh! no available interface for |||%s|||?\n", SKYPIAX_P_LOG, interface_name);
+                       DEBUGA_SKYPE("2 SESSION_DESTROY %s\n", SKYPIAX_P_LOG, switch_core_session_get_uuid(*new_session));
+                       switch_core_session_destroy(new_session);
+                       switch_mutex_unlock(globals.mutex);
+                       //return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+                       return SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION;
+               }
+
+               channel = switch_core_session_get_channel(*new_session);
+               if (!channel) {
+                       ERRORA("Doh! no channel?\n", SKYPIAX_P_LOG);
+                       switch_core_session_destroy(new_session);
+                       switch_mutex_unlock(globals.mutex);
+                       return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+               }
+               if (skypiax_tech_init(tech_pvt, *new_session) != SWITCH_STATUS_SUCCESS) {
+                       ERRORA("Doh! no tech_init?\n", SKYPIAX_P_LOG);
+                       switch_core_session_destroy(new_session);
+                       switch_mutex_unlock(globals.mutex);
+                       return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+               }
+
+
+               if (outbound_profile) {
+                       char name[128];
+
+                       if (strncmp("ANY", outbound_profile->destination_number, 3) == 0) {
+                               snprintf(name, sizeof(name), "skypiax/ANY/%s%s", tech_pvt->name, outbound_profile->destination_number + 3);
+                       } else if (strncmp("RR", outbound_profile->destination_number, 2) == 0) {
+                               snprintf(name, sizeof(name), "skypiax/RR/%s%s", tech_pvt->name, outbound_profile->destination_number + 2);
+                       } else {
+                               snprintf(name, sizeof(name), "skypiax/%s", outbound_profile->destination_number);
+                       }
+
+                       //snprintf(name, sizeof(name), "skypiax/%s", outbound_profile->destination_number);
+                       //snprintf(name, sizeof(name), "skypiax/%s", tech_pvt->name);
+                       switch_channel_set_name(channel, name);
+                       caller_profile = switch_caller_profile_clone(*new_session, outbound_profile);
+                       switch_channel_set_caller_profile(channel, caller_profile);
+                       tech_pvt->caller_profile = caller_profile;
+               } else {
+                       ERRORA("Doh! no caller profile\n", SKYPIAX_P_LOG);
+                       switch_core_session_destroy(new_session);
+                       switch_mutex_unlock(globals.mutex);
+                       return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+               }
+
+               tech_pvt->ob_calls++;
+
+               rdest = strchr(caller_profile->destination_number, '/');
+               *rdest++ = '\0';
+
+               //skypiax_call(tech_pvt, rdest, 30);
+
+               switch_copy_string(tech_pvt->session_uuid_str, switch_core_session_get_uuid(*new_session), sizeof(tech_pvt->session_uuid_str));
+               caller_profile = tech_pvt->caller_profile;
+               caller_profile->destination_number = rdest;
+
+               switch_channel_set_flag(channel, CF_OUTBOUND);
+               switch_set_flag(tech_pvt, TFLAG_OUTBOUND);
+               switch_channel_set_state(channel, CS_INIT);
+               skypiax_call(tech_pvt, rdest, 30);
+               switch_mutex_unlock(globals.mutex);
+               return SWITCH_CAUSE_SUCCESS;
+       }
+
+       ERRORA("Doh! no new_session\n", SKYPIAX_P_LOG);
+       return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+}
+
+/*!
+ * \brief This thread runs during a call, and monitor the interface for signaling, like hangup, caller id, etc most of signaling is handled inside the skypiax_signaling_read function
+ *
+ */
+static void *SWITCH_THREAD_FUNC skypiax_signaling_thread_func(switch_thread_t * thread, void *obj)
+{
+       private_t *tech_pvt = obj;
+       int res;
+       int forever = 1;
+
+       if (!tech_pvt)
+               return NULL;
+
+       DEBUGA_SKYPE("In skypiax_signaling_thread_func: started, p=%p\n", SKYPIAX_P_LOG, (void *) tech_pvt);
+
+       while (forever) {
+               if (!(running && tech_pvt->running))
+                       break;
+               res = skypiax_signaling_read(tech_pvt);
+               if (res == CALLFLOW_INCOMING_HANGUP) {
+                       switch_core_session_t *session = NULL;
+                       switch_channel_t *channel = NULL;
+                       //private_t *tech_pvt = NULL;
+                       DEBUGA_SKYPE("skype call ended\n", SKYPIAX_P_LOG);
+
+                       if (tech_pvt) {
+                               session = switch_core_session_locate(tech_pvt->session_uuid_str);
+                               if (session) {
+                                       channel = switch_core_session_get_channel(session);
+                                       if (channel) {
+                                               switch_channel_state_t state = switch_channel_get_state(channel);
+                                               if (state < CS_EXECUTE) {
+                                                       switch_sleep(10000);    //10 msec, let the state evolve from CS_NEW
+                                               }
+                                               switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
+                                       } else {
+                                               ERRORA("no channel?\n", SKYPIAX_P_LOG);
+                                       }
+                                       switch_core_session_rwunlock(session);
+                               } else {
+                                       DEBUGA_SKYPE("no session\n", SKYPIAX_P_LOG);
+                               }
+                               switch_mutex_lock(globals.mutex);
+                               tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                               *tech_pvt->session_uuid_str = '\0';
+                               *tech_pvt->skype_call_id = '\0';
+                               switch_mutex_unlock(globals.mutex);
+
+                               //ERRORA("LET'S WAIT\n", SKYPIAX_P_LOG);
+                               switch_sleep(300000);   //0.3 sec
+                               //ERRORA("WAIT'S OVER\n", SKYPIAX_P_LOG);
+                               //tech_pvt->skype_callflow = CALLFLOW_STATUS_FINISHED;
+                               //switch_sleep(30000);    //0.03 sec
+                               switch_mutex_lock(globals.mutex);
+                               tech_pvt->skype_callflow = CALLFLOW_CALL_IDLE;
+                               tech_pvt->interface_state = SKYPIAX_STATE_IDLE;
+                               switch_mutex_unlock(globals.mutex);
+                       } else {
+                               ERRORA("no tech_pvt?\n", SKYPIAX_P_LOG);
+                       }
+               }
+       }
+       return NULL;
+}
+
+/* BEGIN: Changes heres */
+static switch_status_t load_config(int reload_type)
+/* END: Changes heres */
+{
+       char *cf = "skypiax.conf";
+       switch_xml_t cfg, xml, global_settings, param, interfaces, myinterface;
+       private_t *tech_pvt = NULL;
+
+       switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, skypiax_module_pool);
+       if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
+               ERRORA("open of %s failed\n", SKYPIAX_P_LOG, cf);
+               running = 0;
+               switch_xml_free(xml);
+               return SWITCH_STATUS_TERM;
+       }
+
+       switch_mutex_lock(globals.mutex);
+       if ((global_settings = switch_xml_child(cfg, "global_settings"))) {
+               for (param = switch_xml_child(global_settings, "param"); param; param = param->next) {
+                       char *var = (char *) switch_xml_attr_soft(param, "name");
+                       char *val = (char *) switch_xml_attr_soft(param, "value");
+
+                       if (!strcasecmp(var, "debug")) {
+                               DEBUGA_SKYPE("globals.debug=%d\n", SKYPIAX_P_LOG, globals.debug);
+                               globals.debug = atoi(val);
+                               DEBUGA_SKYPE("globals.debug=%d\n", SKYPIAX_P_LOG, globals.debug);
+                       } else if (!strcasecmp(var, "hold-music")) {
+                               switch_set_string(globals.hold_music, val);
+                               DEBUGA_SKYPE("globals.hold_music=%s\n", SKYPIAX_P_LOG, globals.hold_music);
+                       } else if (!strcmp(var, "port")) {
+                               globals.port = atoi(val);
+                               DEBUGA_SKYPE("globals.port=%d\n", SKYPIAX_P_LOG, globals.port);
+                       } else if (!strcmp(var, "codec-master")) {
+                               if (!strcasecmp(val, "us")) {
+                                       switch_set_flag(&globals, GFLAG_MY_CODEC_PREFS);
+                               }
+                               DEBUGA_SKYPE("codec-master globals.debug=%d\n", SKYPIAX_P_LOG, globals.debug);
+                       } else if (!strcmp(var, "dialplan")) {
+                               set_global_dialplan(val);
+                               DEBUGA_SKYPE("globals.dialplan=%s\n", SKYPIAX_P_LOG, globals.dialplan);
+                       } else if (!strcmp(var, "destination")) {
+                               set_global_destination(val);
+                               DEBUGA_SKYPE("globals.destination=%s\n", SKYPIAX_P_LOG, globals.destination);
+                       } else if (!strcmp(var, "context")) {
+                               set_global_context(val);
+                               DEBUGA_SKYPE("globals.context=%s\n", SKYPIAX_P_LOG, globals.context);
+                       } else if (!strcmp(var, "codec-prefs")) {
+                               set_global_codec_string(val);
+                               DEBUGA_SKYPE("globals.codec_string=%s\n", SKYPIAX_P_LOG, globals.codec_string);
+                               globals.codec_order_last = switch_separate_string(globals.codec_string, ',', globals.codec_order, SWITCH_MAX_CODECS);
+                       } else if (!strcmp(var, "codec-rates")) {
+                               set_global_codec_rates_string(val);
+                               DEBUGA_SKYPE("globals.codec_rates_string=%s\n", SKYPIAX_P_LOG, globals.codec_rates_string);
+                               globals.codec_rates_last = switch_separate_string(globals.codec_rates_string, ',', globals.codec_rates, SWITCH_MAX_CODECS);
+                       }
+
+               }
+       }
+
+       if ((interfaces = switch_xml_child(cfg, "per_interface_settings"))) {
+               int i = 0;
+
+               for (myinterface = switch_xml_child(interfaces, "interface"); myinterface; myinterface = myinterface->next) {
+                       char *id = (char *) switch_xml_attr(myinterface, "id");
+                       char *name = (char *) switch_xml_attr(myinterface, "name");
+                       char *context = "default";
+                       char *dialplan = "XML";
+                       char *destination = "5000";
+                       char *tonegroup = NULL;
+                       char *digit_timeout = NULL;
+                       char *max_digits = NULL;
+                       char *hotline = NULL;
+                       char *dial_regex = NULL;
+                       char *hold_music = NULL;
+                       char *fail_dial_regex = NULL;
+                       char *enable_callerid = "true";
+                       char *X11_display = NULL;
+                       char *tcp_cli_port = NULL;
+                       char *tcp_srv_port = NULL;
+                       char *skype_user = NULL;
+                       char *report_incoming_chatmessages = "true";
+
+                       uint32_t interface_id = 0, to = 0, max = 0;
+
+                       tech_pvt = NULL;
+
+                       for (param = switch_xml_child(myinterface, "param"); param; param = param->next) {
+                               char *var = (char *) switch_xml_attr_soft(param, "name");
+                               char *val = (char *) switch_xml_attr_soft(param, "value");
+
+                               if (!strcasecmp(var, "tonegroup")) {
+                                       tonegroup = val;
+                               } else if (!strcasecmp(var, "digit_timeout") || !strcasecmp(var, "digit-timeout")) {
+                                       digit_timeout = val;
+                               } else if (!strcasecmp(var, "context")) {
+                                       context = val;
+                               } else if (!strcasecmp(var, "dialplan")) {
+                                       dialplan = val;
+                               } else if (!strcasecmp(var, "destination")) {
+                                       destination = val;
+                               } else if (!strcasecmp(var, "dial-regex")) {
+                                       dial_regex = val;
+                               } else if (!strcasecmp(var, "enable-callerid")) {
+                                       enable_callerid = val;
+                               } else if (!strcasecmp(var, "fail-dial-regex")) {
+                                       fail_dial_regex = val;
+                               } else if (!strcasecmp(var, "hold-music")) {
+                                       hold_music = val;
+                               } else if (!strcasecmp(var, "skype_user")) {
+                                       skype_user = val;
+                               } else if (!strcasecmp(var, "report_incoming_chatmessages")) {
+                                       report_incoming_chatmessages = val;
+                               } else if (!strcasecmp(var, "tcp_cli_port")) {
+                                       tcp_cli_port = val;
+                               } else if (!strcasecmp(var, "tcp_srv_port")) {
+                                       tcp_srv_port = val;
+                               } else if (!strcasecmp(var, "X11-display") || !strcasecmp(var, "X11_display")) {
+                                       X11_display = val;
+                               } else if (!strcasecmp(var, "max_digits") || !strcasecmp(var, "max-digits")) {
+                                       max_digits = val;
+                               } else if (!strcasecmp(var, "hotline")) {
+                                       hotline = val;
+                               }
+
+                       }
+                       if (!skype_user) {
+                               ERRORA("interface missing REQUIRED param 'skype_user'\n", SKYPIAX_P_LOG);
+                               continue;
+                       }
+
+                       /* BEGIN: Changes here */
+                       if (reload_type == SOFT_RELOAD) {
+                               char the_interface[256];
+                               sprintf(the_interface, "#%s", name);
+
+                               if (interface_exists(the_interface) == SWITCH_STATUS_SUCCESS) {
+                                       continue;
+                               }
+                       }
+                       /* END: Changes here */
+
+                       if (!X11_display) {
+                               ERRORA("interface missing REQUIRED param 'X11_display'\n", SKYPIAX_P_LOG);
+                               continue;
+                       }
+                       if (!tcp_cli_port) {
+                               ERRORA("interface missing REQUIRED param 'tcp_cli_port'\n", SKYPIAX_P_LOG);
+                               continue;
+                       }
+
+                       if (!tcp_srv_port) {
+                               ERRORA("interface missing REQUIRED param 'tcp_srv_port'\n", SKYPIAX_P_LOG);
+                               continue;
+                       }
+                       if (!id) {
+                               ERRORA("interface missing REQUIRED param 'id'\n", SKYPIAX_P_LOG);
+                               continue;
+                       }
+                       if (switch_is_number(id)) {
+                               interface_id = atoi(id);
+                               DEBUGA_SKYPE("interface_id=%d\n", SKYPIAX_P_LOG, interface_id);
+                       } else {
+                               ERRORA("interface param 'id' MUST be a number, now id='%s'\n", SKYPIAX_P_LOG, id);
+                               continue;
+                       }
+
+                       if (!name) {
+                               WARNINGA("interface missing param 'name', not nice, but works\n", SKYPIAX_P_LOG);
+                       }
+
+                       if (!tonegroup) {
+                               tonegroup = "us";
+                       }
+
+                       if (digit_timeout) {
+                               to = atoi(digit_timeout);
+                       }
+
+                       if (max_digits) {
+                               max = atoi(max_digits);
+                       }
+
+                       if (name) {
+                               DEBUGA_SKYPE("name=%s\n", SKYPIAX_P_LOG, name);
+                       }
+#ifndef WIN32
+                       if (!XInitThreads()) {
+                               ERRORA("Not initialized XInitThreads!\n", SKYPIAX_P_LOG);
+                       } else {
+                               DEBUGA_SKYPE("Initialized XInitThreads!\n", SKYPIAX_P_LOG);
+                       }
+                       switch_sleep(1000);
+#endif /* WIN32 */
+
+                       if (interface_id && interface_id < SKYPIAX_MAX_INTERFACES) {
+                               private_t newconf;
+                               switch_threadattr_t *skypiax_api_thread_attr = NULL;
+                               switch_threadattr_t *skypiax_signaling_thread_attr = NULL;
+
+                               memset(&newconf, '\0', sizeof(newconf));
+                               globals.SKYPIAX_INTERFACES[interface_id] = newconf;
+                               globals.SKYPIAX_INTERFACES[interface_id].running = 1;
+
+
+                               tech_pvt = &globals.SKYPIAX_INTERFACES[interface_id];
+
+                               switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].interface_id, id);
+                               if (name) {
+                                       switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].name, name);
+                               } else {
+                                       switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].name, "N/A");
+                               }
+                               DEBUGA_SKYPE("CONFIGURING interface_id=%d\n", SKYPIAX_P_LOG, interface_id);
+#ifdef WIN32
+                               globals.SKYPIAX_INTERFACES[interface_id].tcp_cli_port = (unsigned short) atoi(tcp_cli_port);
+                               globals.SKYPIAX_INTERFACES[interface_id].tcp_srv_port = (unsigned short) atoi(tcp_srv_port);
+#else /* WIN32 */
+                               globals.SKYPIAX_INTERFACES[interface_id].tcp_cli_port = atoi(tcp_cli_port);
+                               globals.SKYPIAX_INTERFACES[interface_id].tcp_srv_port = atoi(tcp_srv_port);
+#endif /* WIN32 */
+                               switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].X11_display, X11_display);
+                               switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].skype_user, skype_user);
+                               switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].context, context);
+                               switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].dialplan, dialplan);
+                               switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].destination, destination);
+                               switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].context, context);
+
+                               if (!strcmp(report_incoming_chatmessages, "true") || !strcmp(report_incoming_chatmessages, "1")) {
+                                       globals.SKYPIAX_INTERFACES[interface_id].report_incoming_chatmessages = 1;
+                               } else {
+                                       globals.SKYPIAX_INTERFACES[interface_id].report_incoming_chatmessages = 0;      //redundant, just in case
+
+                               }
+
+                               DEBUGA_SKYPE
+                                       ("interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].X11_display=%s\n",
+                                        SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].X11_display);
+                               DEBUGA_SKYPE
+                                       ("interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].skype_user=%s\n",
+                                        SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].skype_user);
+                               DEBUGA_SKYPE
+                                       ("interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].tcp_cli_port=%d\n",
+                                        SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].tcp_cli_port);
+                               DEBUGA_SKYPE
+                                       ("interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].tcp_srv_port=%d\n",
+                                        SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].tcp_srv_port);
+                               DEBUGA_SKYPE("interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].name=%s\n",
+                                                        SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].name);
+                               DEBUGA_SKYPE
+                                       ("interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].context=%s\n",
+                                        SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].context);
+                               DEBUGA_SKYPE
+                                       ("interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].dialplan=%s\n",
+                                        SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].dialplan);
+                               DEBUGA_SKYPE
+                                       ("interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].destination=%s\n",
+                                        SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].destination);
+                               DEBUGA_SKYPE
+                                       ("interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].context=%s\n",
+                                        SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].context);
+
+                               DEBUGA_SKYPE
+                                       ("interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].report_incoming_chatmessages=%d\n",
+                                        SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].report_incoming_chatmessages);
+
+                               WARNINGA("STARTING interface_id=%d\n", SKYPIAX_P_LOG, interface_id);
+
+                               switch_threadattr_create(&skypiax_api_thread_attr, skypiax_module_pool);
+                               switch_threadattr_detach_set(skypiax_api_thread_attr, 1);
+                               switch_threadattr_stacksize_set(skypiax_api_thread_attr, SWITCH_THREAD_STACKSIZE);
+                               switch_thread_create(&globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread,
+                                                                        skypiax_api_thread_attr, skypiax_do_skypeapi_thread, &globals.SKYPIAX_INTERFACES[interface_id], skypiax_module_pool);
+
+                               switch_sleep(100000);
+
+                               switch_threadattr_create(&skypiax_signaling_thread_attr, skypiax_module_pool);
+                               switch_threadattr_detach_set(skypiax_signaling_thread_attr, 1);
+                               switch_threadattr_stacksize_set(skypiax_signaling_thread_attr, SWITCH_THREAD_STACKSIZE);
+                               switch_thread_create(&globals.SKYPIAX_INTERFACES[interface_id].
+                                                                        skypiax_signaling_thread, skypiax_signaling_thread_attr,
+                                                                        skypiax_signaling_thread_func, &globals.SKYPIAX_INTERFACES[interface_id], skypiax_module_pool);
+
+                               switch_sleep(100000);
+
+                               skypiax_audio_init(&globals.SKYPIAX_INTERFACES[interface_id]);
+                               switch_mutex_init(&globals.SKYPIAX_INTERFACES[interface_id].mutex_audio_srv, SWITCH_MUTEX_NESTED, skypiax_module_pool);
+
+                               NOTICA
+                                       ("WAITING roughly 10 seconds to find a running Skype client and connect to its SKYPE API for interface_id=%d\n",
+                                        SKYPIAX_P_LOG, interface_id);
+                               i = 0;
+                               while (globals.SKYPIAX_INTERFACES[interface_id].SkypiaxHandles.api_connected == 0 && running && i < 200) {      // 10 seconds! thanks Jeff Lenk
+                                       switch_sleep(50000);
+                                       i++;
+                               }
+                               if (globals.SKYPIAX_INTERFACES[interface_id].SkypiaxHandles.api_connected) {
+                                       NOTICA
+                                               ("Found a running Skype client, connected to its SKYPE API for interface_id=%d, waiting 60 seconds for CURRENTUSERHANDLE==%s\n",
+                                                SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].skype_user);
+                               } else {
+                                       ERRORA
+                                               ("Failed to connect to a SKYPE API for interface_id=%d, no SKYPE client running, please (re)start Skype client. Skypiax exiting\n",
+                                                SKYPIAX_P_LOG, interface_id);
+                                       running = 0;
+                                       switch_mutex_unlock(globals.mutex);
+                                       switch_xml_free(xml);
+                                       return SWITCH_STATUS_FALSE;
+                               }
+
+                               i = 0;
+                               while (globals.SKYPIAX_INTERFACES[interface_id].SkypiaxHandles.currentuserhandle == 0 && running && i < 1200) { // 60 seconds! thanks Jeff Lenk
+                                       switch_sleep(50000);
+                                       i++;
+                               }
+                               if (globals.SKYPIAX_INTERFACES[interface_id].SkypiaxHandles.currentuserhandle) {
+                                       WARNINGA
+                                               ("Interface_id=%d is now STARTED, the Skype client to which we are connected gave us the correct CURRENTUSERHANDLE (%s)\n",
+                                                SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].skype_user);
+
+
+                                       skypiax_signaling_write(&globals.SKYPIAX_INTERFACES[interface_id], "PROTOCOL 7");
+                                       switch_sleep(10000);
+                                       skypiax_signaling_write(&globals.SKYPIAX_INTERFACES[interface_id], "SET AUTOAWAY OFF");
+                               } else {
+                                       ERRORA
+                                               ("The Skype client to which we are connected FAILED to gave us CURRENTUSERHANDLE=%s, interface_id=%d FAILED to start. No Skype client logged in as '%s' has been found. Please (re)launch a Skype client logged in as '%s'. Skypiax exiting now\n",
+                                                SKYPIAX_P_LOG, globals.SKYPIAX_INTERFACES[interface_id].skype_user,
+                                                interface_id, globals.SKYPIAX_INTERFACES[interface_id].skype_user, globals.SKYPIAX_INTERFACES[interface_id].skype_user);
+                                       running = 0;
+                                       switch_mutex_unlock(globals.mutex);
+                                       switch_xml_free(xml);
+                                       return SWITCH_STATUS_FALSE;
+                               }
+
+                       } else {
+                               ERRORA("interface id %d is higher than SKYPIAX_MAX_INTERFACES (%d)\n", SKYPIAX_P_LOG, interface_id, SKYPIAX_MAX_INTERFACES);
+                               continue;
+                       }
+
+               }
+
+               for (i = 0; i < SKYPIAX_MAX_INTERFACES; i++) {
+                       if (strlen(globals.SKYPIAX_INTERFACES[i].name)) {
+                               /* How many real intterfaces */
+                               globals.real_interfaces = i + 1;
+
+                               tech_pvt = &globals.SKYPIAX_INTERFACES[i];
+
+                               DEBUGA_SKYPE("i=%d globals.SKYPIAX_INTERFACES[%d].interface_id=%s\n", SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].interface_id);
+                               DEBUGA_SKYPE("i=%d globals.SKYPIAX_INTERFACES[%d].X11_display=%s\n", SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].X11_display);
+                               DEBUGA_SKYPE("i=%d globals.SKYPIAX_INTERFACES[%d].name=%s\n", SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].name);
+                               DEBUGA_SKYPE("i=%d globals.SKYPIAX_INTERFACES[%d].context=%s\n", SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].context);
+                               DEBUGA_SKYPE("i=%d globals.SKYPIAX_INTERFACES[%d].dialplan=%s\n", SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].dialplan);
+                               DEBUGA_SKYPE("i=%d globals.SKYPIAX_INTERFACES[%d].destination=%s\n", SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].destination);
+                               DEBUGA_SKYPE("i=%d globals.SKYPIAX_INTERFACES[%d].context=%s\n", SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].context);
+                               DEBUGA_SKYPE("i=%d globals.SKYPIAX_INTERFACES[%d].report_incoming_chatmessages=%d\n", SKYPIAX_P_LOG, i, i,
+                                                        globals.SKYPIAX_INTERFACES[i].report_incoming_chatmessages);
+                       }
+               }
+       }
+
+       switch_mutex_unlock(globals.mutex);
+       switch_xml_free(xml);
+
+       return SWITCH_STATUS_SUCCESS;
+}
+static switch_status_t chat_send(const char *proto, const char *from, const char *to, const char *subject, const char *body, const char *type,
+                                                                const char *hint)
+{
+       //char *user, *host, *f_user = NULL, *ffrom = NULL, *f_host = NULL, *f_resource = NULL;
+       char *user = NULL, *host, *f_user = NULL, *f_host = NULL, *f_resource = NULL;
+       //mdl_profile_t *profile = NULL;
+       private_t *tech_pvt = NULL;
+       int i = 0, found = 0, tried = 0;
+       char skype_msg[1024];
+
+       switch_assert(proto != NULL);
+
+       DEBUGA_SKYPE("chat_send(proto=%s, from=%s, to=%s, subject=%s, body=%s, type=%s, hint=%s)\n", SKYPIAX_P_LOG, proto, from, to, subject, body, type,
+                                hint ? hint : "NULL");
+
+       if (!to || !strlen(to)) {
+               ERRORA("Missing To: header.\n", SKYPIAX_P_LOG);
+               return SWITCH_STATUS_SUCCESS;
+       }
+
+       if ((!from && !hint) || (!strlen(from) && !strlen(hint))) {
+               ERRORA("Missing From: AND Hint: headers.\n", SKYPIAX_P_LOG);
+               return SWITCH_STATUS_SUCCESS;
+       }
+
+       if (from && (f_user = strdup(from))) {
+               if ((f_host = strchr(f_user, '@'))) {
+                       *f_host++ = '\0';
+                       if ((f_resource = strchr(f_host, '/'))) {
+                               *f_resource++ = '\0';
+                       }
+               }
+       }
+
+       if (to && (user = strdup(to))) {
+               if ((host = strchr(user, '@'))) {
+                       *host++ = '\0';
+               }
+               //if (!strcmp(proto, MDL_CHAT_PROTO)) {
+
+               DEBUGA_SKYPE("chat_send(proto=%s, from=%s, to=%s, subject=%s, body=%s, type=%s, hint=%s)\n", SKYPIAX_P_LOG, proto, from, to, subject, body, type,
+                                        hint ? hint : "NULL");
+               if (hint && strlen(hint)) {
+                       //in hint we receive the interface name to use
+                       for (i = 0; !found && i < SKYPIAX_MAX_INTERFACES; i++) {
+                               if (strlen(globals.SKYPIAX_INTERFACES[i].name)
+                                       && (strncmp(globals.SKYPIAX_INTERFACES[i].name, hint, strlen(hint)) == 0)) {
+                                       tech_pvt = &globals.SKYPIAX_INTERFACES[i];
+                                       DEBUGA_SKYPE("Using interface: globals.SKYPIAX_INTERFACES[%d].name=|||%s|||\n", SKYPIAX_P_LOG, i, globals.SKYPIAX_INTERFACES[i].name);
+                                       found = 1;
+                                       break;
+                               }
+                       }
+               } else {
+                       //we have no a predefined interface name to use (hint is NULL), so let's choose an interface from the username (from)
+                       for (i = 0; !found && i < SKYPIAX_MAX_INTERFACES; i++) {
+                               if (strlen(globals.SKYPIAX_INTERFACES[i].name)
+                                       && (strncmp(globals.SKYPIAX_INTERFACES[i].skype_user, from, strlen(from)) == 0)) {
+                                       tech_pvt = &globals.SKYPIAX_INTERFACES[i];
+                                       DEBUGA_SKYPE("Using interface: globals.SKYPIAX_INTERFACES[%d].name=|||%s|||\n", SKYPIAX_P_LOG, i, globals.SKYPIAX_INTERFACES[i].name);
+                                       found = 1;
+                                       break;
+                               }
+                       }
+               }
+               if (!found) {
+                       ERRORA("ERROR: A Skypiax interface with name='%s' or one with skypeuser='%s' was not found\n", SKYPIAX_P_LOG, hint ? hint : "NULL",
+                                  from ? from : "NULL");
+                       goto end;
+               } else {
+
+                       snprintf(skype_msg, sizeof(skype_msg), "CHAT CREATE %s", to);
+                       skypiax_signaling_write(tech_pvt, skype_msg);
+                       switch_sleep(1000);
+               }
+               //} else {
+               //FIXME don't know how to do here, let's hope this is correct
+               //char *p;
+               //ffrom = switch_mprintf("%s+%s", proto, from);
+               //from = ffrom;
+               //if ((p = strchr(from, '/'))) {
+               //*p = '\0';
+               //}
+               //NOTICA("chat_send(proto=%s, from=%s, to=%s, subject=%s, body=%s, type=%s, hint=%s)\n", SKYPIAX_P_LOG, proto, from, to, subject, body, type, hint?hint:"NULL");
+               //switch_core_chat_send(proto, proto, from, to, subject, body, type, hint);
+               //return SWITCH_STATUS_SUCCESS;
+               //}
+
+               found = 0;
+
+               while (!found) {
+                       for (i = 0; i < MAX_CHATS; i++) {
+                               if (!strcmp(tech_pvt->chats[i].dialog_partner, to)) {
+                                       snprintf(skype_msg, sizeof(skype_msg), "CHATMESSAGE %s %s", tech_pvt->chats[i].chatname, body);
+                                       skypiax_signaling_write(tech_pvt, skype_msg);
+                                       found = 1;
+                                       break;
+                               }
+                       }
+                       if (found) {
+                               break;
+                       }
+                       if (tried > 1000) {
+                               ERRORA("No chat with dialog_partner='%s' was found\n", SKYPIAX_P_LOG, to);
+                               break;
+                       }
+                       switch_sleep(1000);
+               }
+
+       }
+  end:
+       switch_safe_free(user);
+       switch_safe_free(f_user);
+       return SWITCH_STATUS_SUCCESS;
+}
+
+
+SWITCH_MODULE_LOAD_FUNCTION(mod_skypiax_load)
+{
+       switch_api_interface_t *commands_api_interface;
+       switch_chat_interface_t *chat_interface;
+
+       skypiax_module_pool = pool;
+       memset(&globals, '\0', sizeof(globals));
+
+       running = 1;
+
+       if (load_config(FULL_RELOAD) != SWITCH_STATUS_SUCCESS) {
+               running = 0;
+               return SWITCH_STATUS_FALSE;
+       }
+
+       if (switch_event_reserve_subclass(MY_EVENT_INCOMING_CHATMESSAGE) != SWITCH_STATUS_SUCCESS) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass!\n");
+               return SWITCH_STATUS_GENERR;
+       }
+
+       *module_interface = switch_loadable_module_create_module_interface(pool, modname);
+       skypiax_endpoint_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE);
+       skypiax_endpoint_interface->interface_name = "skypiax";
+       skypiax_endpoint_interface->io_routines = &skypiax_io_routines;
+       skypiax_endpoint_interface->state_handler = &skypiax_state_handlers;
+
+       if (running) {
+
+               SWITCH_ADD_API(commands_api_interface, "sk", "Skypiax console commands", sk_function, SK_SYNTAX);
+               SWITCH_ADD_API(commands_api_interface, "skypiax", "Skypiax interface commands", skypiax_function, SKYPIAX_SYNTAX);
+               SWITCH_ADD_API(commands_api_interface, "skypiax_chat", "Skypiax_chat interface remote_skypename TEXT", skypiax_chat_function, SKYPIAX_CHAT_SYNTAX);
+               SWITCH_ADD_CHAT(chat_interface, MDL_CHAT_PROTO, chat_send);
+
+
+               /* indicate that the module should continue to be loaded */
+               return SWITCH_STATUS_SUCCESS;
+       } else
+               return SWITCH_STATUS_FALSE;
+}
+
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_skypiax_shutdown)
+{
+       int x;
+       private_t *tech_pvt = NULL;
+       switch_status_t status;
+       unsigned int howmany = 8;
+       int interface_id;
+
+       running = 0;
+
+       for (interface_id = 0; interface_id < SKYPIAX_MAX_INTERFACES; interface_id++) {
+               tech_pvt = &globals.SKYPIAX_INTERFACES[interface_id];
+
+               if (strlen(globals.SKYPIAX_INTERFACES[interface_id].name)) {
+                       if (globals.SKYPIAX_INTERFACES[interface_id].skypiax_signaling_thread) {
+#ifdef WIN32
+                               switch_file_write(tech_pvt->SkypiaxHandles.fdesc[1], "sciutati", &howmany);     // let's the controldev_thread die
+#else /* WIN32 */
+                               howmany = write(tech_pvt->SkypiaxHandles.fdesc[1], "sciutati", howmany);
+#endif /* WIN32 */
+                       }
+
+                       if (globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread) {
+#ifdef WIN32
+                               if (SendMessage(tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle, WM_DESTROY, 0, 0) == FALSE) {    // let's the skypiax_api_thread_func die
+                                       DEBUGA_SKYPE("got FALSE here, thread probably was already dead. GetLastError returned: %d\n", SKYPIAX_P_LOG, GetLastError());
+                                       globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread = NULL;
+                               }
+#else
+                               if (tech_pvt->SkypiaxHandles.disp) {
+                                       XEvent e;
+                                       Atom atom1 = XInternAtom(tech_pvt->SkypiaxHandles.disp, "SKYPECONTROLAPI_MESSAGE_BEGIN",
+                                                                                        False);
+                                       memset(&e, 0, sizeof(e));
+                                       e.xclient.type = ClientMessage;
+                                       e.xclient.message_type = atom1; /*  leading message */
+                                       e.xclient.display = tech_pvt->SkypiaxHandles.disp;
+                                       e.xclient.window = tech_pvt->SkypiaxHandles.skype_win;
+                                       e.xclient.format = 8;
+
+                                       XSendEvent(tech_pvt->SkypiaxHandles.disp, tech_pvt->SkypiaxHandles.win, False, 0, &e);
+                                       XSync(tech_pvt->SkypiaxHandles.disp, False);
+                               }
+#endif
+                       }
+                       x = 10;
+                       while (x) {                     //FIXME 0.5 seconds?
+                               x--;
+                               switch_yield(50000);
+                       }
+                       if (globals.SKYPIAX_INTERFACES[interface_id].skypiax_signaling_thread) {
+                               switch_thread_join(&status, globals.SKYPIAX_INTERFACES[interface_id].skypiax_signaling_thread);
+                       }
+                       if (globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread) {
+                               switch_thread_join(&status, globals.SKYPIAX_INTERFACES[interface_id].skypiax_api_thread);
+                       }
+#ifndef WIN32
+                       WARNINGA("SHUTDOWN interface_id=%d\n", SKYPIAX_P_LOG, interface_id);
+                       shutdown(tech_pvt->audiopipe_cli[0], 2);
+                       close(tech_pvt->audiopipe_cli[0]);
+                       shutdown(tech_pvt->audiopipe_cli[1], 2);
+                       close(tech_pvt->audiopipe_cli[1]);
+                       shutdown(tech_pvt->audiopipe_srv[0], 2);
+                       close(tech_pvt->audiopipe_srv[0]);
+                       shutdown(tech_pvt->audiopipe_srv[1], 2);
+                       close(tech_pvt->audiopipe_srv[1]);
+                       shutdown(tech_pvt->SkypiaxHandles.fdesc[0], 2);
+                       close(tech_pvt->SkypiaxHandles.fdesc[0]);
+                       shutdown(tech_pvt->SkypiaxHandles.fdesc[1], 2);
+                       close(tech_pvt->SkypiaxHandles.fdesc[1]);
+#endif /* WIN32 */
+               }
+
+       }
+       switch_event_free_subclass(MY_EVENT_INCOMING_CHATMESSAGE);
+
+       switch_safe_free(globals.dialplan);
+       switch_safe_free(globals.context);
+       switch_safe_free(globals.destination);
+       switch_safe_free(globals.codec_string);
+       switch_safe_free(globals.codec_rates_string);
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
+void *SWITCH_THREAD_FUNC skypiax_do_tcp_srv_thread(switch_thread_t * thread, void *obj)
+{
+       return skypiax_do_tcp_srv_thread_func(obj);
+}
+
+void *SWITCH_THREAD_FUNC skypiax_do_tcp_cli_thread(switch_thread_t * thread, void *obj)
+{
+       return skypiax_do_tcp_cli_thread_func(obj);
+}
+
+void *SWITCH_THREAD_FUNC skypiax_do_skypeapi_thread(switch_thread_t * thread, void *obj)
+{
+       return skypiax_do_skypeapi_thread_func(obj);
+}
+
+int dtmf_received(private_t * tech_pvt, char *value)
+{
+       switch_core_session_t *session = NULL;
+       switch_channel_t *channel = NULL;
+
+       session = switch_core_session_locate(tech_pvt->session_uuid_str);
+       channel = switch_core_session_get_channel(session);
+
+       if (channel) {
+
+               if (!switch_channel_test_flag(channel, CF_BRIDGED)) {
+
+                       switch_dtmf_t dtmf = { (char) value[0], switch_core_default_dtmf_duration(0) };
+                       DEBUGA_SKYPE("received DTMF %c on channel %s\n", SKYPIAX_P_LOG, dtmf.digit, switch_channel_get_name(channel));
+                       switch_mutex_lock(tech_pvt->flag_mutex);
+                       //FIXME: why sometimes DTMFs from here do not seems to be get by FS?
+                       switch_channel_queue_dtmf(channel, &dtmf);
+                       switch_set_flag(tech_pvt, TFLAG_DTMF);
+                       switch_mutex_unlock(tech_pvt->flag_mutex);
+               } else {
+                       NOTICA
+                               ("received a DTMF on channel %s, but we're BRIDGED, so let's NOT relay it out of band\n", SKYPIAX_P_LOG, switch_channel_get_name(channel));
+               }
+       } else {
+               WARNINGA("received %c DTMF, but no channel?\n", SKYPIAX_P_LOG, value[0]);
+       }
+       switch_core_session_rwunlock(session);
+
+       return 0;
+}
+
+int start_audio_threads(private_t * tech_pvt)
+{
+       switch_threadattr_t *thd_attr = NULL;
+
+       switch_threadattr_create(&thd_attr, skypiax_module_pool);
+       switch_threadattr_detach_set(thd_attr, 1);
+       switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
+       if (switch_thread_create(&tech_pvt->tcp_srv_thread, thd_attr, skypiax_do_tcp_srv_thread, tech_pvt, skypiax_module_pool) == SWITCH_STATUS_SUCCESS) {
+               DEBUGA_SKYPE("started tcp_srv_thread thread.\n", SKYPIAX_P_LOG);
+       } else {
+               ERRORA("failed to start tcp_srv_thread thread.\n", SKYPIAX_P_LOG);
+               return -1;
+       }
+
+       switch_threadattr_create(&thd_attr, skypiax_module_pool);
+       switch_threadattr_detach_set(thd_attr, 1);
+       switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
+       if (switch_thread_create(&tech_pvt->tcp_cli_thread, thd_attr, skypiax_do_tcp_cli_thread, tech_pvt, skypiax_module_pool) == SWITCH_STATUS_SUCCESS) {
+               DEBUGA_SKYPE("started tcp_cli_thread thread.\n", SKYPIAX_P_LOG);
+       } else {
+               ERRORA("failed to start tcp_cli_thread thread.\n", SKYPIAX_P_LOG);
+               return -1;
+       }
+       switch_sleep(100000);
+
+       if (tech_pvt->tcp_cli_thread == NULL || tech_pvt->tcp_srv_thread == NULL) {
+               ERRORA("tcp_cli_thread or tcp_srv_thread exited\n", SKYPIAX_P_LOG);
+               return -1;
+       }
+
+       return 0;
+}
+
+int new_inbound_channel(private_t * tech_pvt)
+{
+       switch_core_session_t *session = NULL;
+       switch_channel_t *channel = NULL;
+
+       if ((session = switch_core_session_request(skypiax_endpoint_interface, SWITCH_CALL_DIRECTION_INBOUND, NULL)) != 0) {
+               DEBUGA_SKYPE("2 SESSION_REQUEST %s\n", SKYPIAX_P_LOG, switch_core_session_get_uuid(session));
+               switch_core_session_add_stream(session, NULL);
+               channel = switch_core_session_get_channel(session);
+               if (!channel) {
+                       ERRORA("Doh! no channel?\n", SKYPIAX_P_LOG);
+                       switch_core_session_destroy(&session);
+                       return 0;
+               }
+               if (skypiax_tech_init(tech_pvt, session) != SWITCH_STATUS_SUCCESS) {
+                       ERRORA("Doh! no tech_init?\n", SKYPIAX_P_LOG);
+                       switch_core_session_destroy(&session);
+                       return 0;
+               }
+
+               if ((tech_pvt->caller_profile =
+                        switch_caller_profile_new(switch_core_session_get_pool(session), "skypiax",
+                                                                          tech_pvt->dialplan, tech_pvt->callid_name,
+                                                                          tech_pvt->callid_number, NULL, NULL, NULL, NULL, "mod_skypiax", tech_pvt->context, tech_pvt->destination)) != 0) {
+                       char name[128];
+                       //switch_snprintf(name, sizeof(name), "skypiax/%s/%s", tech_pvt->name, tech_pvt->caller_profile->destination_number);
+                       switch_snprintf(name, sizeof(name), "skypiax/%s", tech_pvt->name);
+                       switch_channel_set_name(channel, name);
+                       switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
+               }
+               switch_channel_set_state(channel, CS_INIT);
+               if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) {
+                       ERRORA("Error spawning thread\n", SKYPIAX_P_LOG);
+                       switch_core_session_destroy(&session);
+                       return 0;
+               }
+       }
+       if (channel) {
+               switch_channel_mark_answered(channel);
+       }
+
+       DEBUGA_SKYPE("new_inbound_channel\n", SKYPIAX_P_LOG);
+
+       return 0;
+}
+
+int remote_party_is_ringing(private_t * tech_pvt)
+{
+       switch_core_session_t *session = NULL;
+       switch_channel_t *channel = NULL;
+
+       if (!zstr(tech_pvt->session_uuid_str)) {
+               session = switch_core_session_locate(tech_pvt->session_uuid_str);
+       } else {
+               ERRORA("No session???\n", SKYPIAX_P_LOG);
+               goto done;
+       }
+       if (session) {
+               channel = switch_core_session_get_channel(session);
+       } else {
+               ERRORA("No session???\n", SKYPIAX_P_LOG);
+               goto done;
+       }
+       if (channel) {
+               switch_channel_mark_ring_ready(channel);
+               DEBUGA_SKYPE("skype_call: REMOTE PARTY RINGING\n", SKYPIAX_P_LOG);
+       } else {
+               ERRORA("No channel???\n", SKYPIAX_P_LOG);
+       }
+
+       switch_core_session_rwunlock(session);
+
+  done:
+       return 0;
+}
+
+int remote_party_is_early_media(private_t * tech_pvt)
+{
+       switch_core_session_t *session = NULL;
+       switch_channel_t *channel = NULL;
+
+       if (!zstr(tech_pvt->session_uuid_str)) {
+               session = switch_core_session_locate(tech_pvt->session_uuid_str);
+       } else {
+               ERRORA("No session???\n\n\n", SKYPIAX_P_LOG);
+               //TODO: kill the bastard
+               goto done;
+       }
+       if (session) {
+               channel = switch_core_session_get_channel(session);
+               switch_core_session_add_stream(session, NULL);
+       } else {
+               ERRORA("No session???\n", SKYPIAX_P_LOG);
+               //TODO: kill the bastard
+               goto done;
+       }
+       if (channel) {
+               switch_channel_mark_pre_answered(channel);
+               DEBUGA_SKYPE("skype_call: REMOTE PARTY EARLY MEDIA\n", SKYPIAX_P_LOG);
+       } else {
+               ERRORA("No channel???\n", SKYPIAX_P_LOG);
+               //TODO: kill the bastard
+       }
+
+       switch_core_session_rwunlock(session);
+
+  done:
+       return 0;
+}
+
+int outbound_channel_answered(private_t * tech_pvt)
+{
+       switch_core_session_t *session = NULL;
+       switch_channel_t *channel = NULL;
+
+       if (!zstr(tech_pvt->session_uuid_str)) {
+               session = switch_core_session_locate(tech_pvt->session_uuid_str);
+       } else {
+               ERRORA("No session???\n", SKYPIAX_P_LOG);
+               goto done;
+       }
+       if (session) {
+               channel = switch_core_session_get_channel(session);
+       } else {
+               ERRORA("No channel???\n", SKYPIAX_P_LOG);
+               goto done;
+       }
+       if (channel) {
+               switch_channel_mark_answered(channel);
+               //DEBUGA_SKYPE("skype_call: %s, answered\n", SKYPIAX_P_LOG, id);
+       } else {
+               ERRORA("No channel???\n", SKYPIAX_P_LOG);
+       }
+
+       switch_core_session_rwunlock(session);
+
+  done:
+       DEBUGA_SKYPE("outbound_channel_answered!\n", SKYPIAX_P_LOG);
+
+       return 0;
+}
+
+private_t *find_available_skypiax_interface_rr(private_t * tech_pvt_calling)
+{
+       private_t *tech_pvt = NULL;
+       int i;
+       //int num_interfaces = SKYPIAX_MAX_INTERFACES; 
+       //int num_interfaces = globals.real_interfaces;
+
+       switch_mutex_lock(globals.mutex);
+
+       /* Fact is the real interface start from 1 */
+       //XXX no, is just a convention, but you can have it start from 0. I do not, for aestetic reasons :-)  
+       //if (globals.next_interface == 0) globals.next_interface = 1;
+
+       for (i = 0; i < SKYPIAX_MAX_INTERFACES; i++) {
+               int interface_id;
+
+               interface_id = globals.next_interface;
+               //interface_id = interface_id < SKYPIAX_MAX_INTERFACES ? interface_id : interface_id - SKYPIAX_MAX_INTERFACES + 1;
+               globals.next_interface = interface_id + 1 < SKYPIAX_MAX_INTERFACES ? interface_id + 1 : 0;
+
+               if (strlen(globals.SKYPIAX_INTERFACES[interface_id].name)) {
+                       int skype_state = 0;
+
+                       tech_pvt = &globals.SKYPIAX_INTERFACES[interface_id];
+                       skype_state = tech_pvt->interface_state;
+                       //DEBUGA_SKYPE("skype interface: %d, name: %s, state: %d\n", SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].name, skype_state);
+                       if ((tech_pvt_calling ? strcmp(tech_pvt->skype_user, tech_pvt_calling->skype_user) : 1)
+                               && (SKYPIAX_STATE_DOWN == skype_state || 0 == skype_state) && (tech_pvt->skype_callflow == CALLFLOW_STATUS_FINISHED
+                                                                                                                                                          || 0 == tech_pvt->skype_callflow)) {
+                               DEBUGA_SKYPE("returning as available skype interface name: %s, state: %d callflow: %d\n", SKYPIAX_P_LOG, tech_pvt->name, skype_state,
+                                                        tech_pvt->skype_callflow);
+                               /*set to Dialing state to avoid other thread fint it, don't know if it is safe */
+                               //XXX no, it's not safe 
+                               if (tech_pvt_calling == NULL) {
+                                       tech_pvt->interface_state = SKYPIAX_STATE_SELECTED;
+                               }
+
+                               switch_mutex_unlock(globals.mutex);
+                               return tech_pvt;
+                       }
+               }                                               // else {
+               //DEBUGA_SKYPE("Skype interface: %d blank!! A hole here means we cannot hunt the last interface.\n", SKYPIAX_P_LOG, interface_id);
+               //}
+       }
+
+       switch_mutex_unlock(globals.mutex);
+       return NULL;
+}
+
+SWITCH_STANDARD_API(sk_function)
+{
+       char *mycmd = NULL, *argv[10] = { 0 };
+       int argc = 0;
+
+       if (globals.sk_console)
+               stream->write_function(stream, "sk console is: |||%s|||\n", globals.sk_console->name);
+       else
+               stream->write_function(stream, "sk console is NOT yet assigned\n");
+
+       if (!zstr(cmd) && (mycmd = strdup(cmd))) {
+               argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+       }
+
+       if (!argc || !argv[0]) {
+               stream->write_function(stream, "%s", SK_SYNTAX);
+               goto end;
+       }
+
+       if (!strcasecmp(argv[0], "list")) {
+               int i;
+               int ib = 0;
+               int ib_failed = 0;
+               int ob = 0;
+               int ob_failed = 0;
+               char next_flag_char = ' ';
+
+               stream->write_function(stream, "F ID\t    Name    \tIB (F/T)    OB (F/T)\tState\tCallFlw\t\tUUID\n");
+               stream->write_function(stream, "= ====\t  ========  \t=======     =======\t======\t============\t======\n");
+
+               for (i = 0; i < SKYPIAX_MAX_INTERFACES; i++) {
+                       next_flag_char = i == globals.next_interface ? '*' : ' ';
+                       ib += globals.SKYPIAX_INTERFACES[i].ib_calls;
+                       ib_failed += globals.SKYPIAX_INTERFACES[i].ib_failed_calls;
+                       ob += globals.SKYPIAX_INTERFACES[i].ob_calls;
+                       ob_failed += globals.SKYPIAX_INTERFACES[i].ob_failed_calls;
+
+                       if (strlen(globals.SKYPIAX_INTERFACES[i].name)) {
+                               stream->write_function(stream,
+                                                                          "%c %d\t[%s]\t%3u/%u\t%6u/%u\t%s\t%s\t%s\n",
+                                                                          next_flag_char,
+                                                                          i, globals.SKYPIAX_INTERFACES[i].name,
+                                                                          globals.SKYPIAX_INTERFACES[i].ib_failed_calls,
+                                                                          globals.SKYPIAX_INTERFACES[i].ib_calls,
+                                                                          globals.SKYPIAX_INTERFACES[i].ob_failed_calls,
+                                                                          globals.SKYPIAX_INTERFACES[i].ob_calls,
+                                                                          interface_status[globals.SKYPIAX_INTERFACES[i].interface_state],
+                                                                          skype_callflow[globals.SKYPIAX_INTERFACES[i].skype_callflow], globals.SKYPIAX_INTERFACES[i].session_uuid_str);
+                       } else if (argc > 1 && !strcasecmp(argv[1], "full")) {
+                               stream->write_function(stream, "%c\t%d\n", next_flag_char, i);
+                       }
+
+               }
+               stream->write_function(stream, "\nTotal Interfaces: %d  IB Calls(Failed/Total): %ld/%ld  OB Calls(Failed/Total): %ld/%ld\n",
+                                                          globals.real_interfaces > 0 ? globals.real_interfaces - 1 : 0, ib_failed, ib, ob_failed, ob);
+
+       } else if (!strcasecmp(argv[0], "console")) {
+               int i;
+               int found = 0;
+
+               if (argc == 2) {
+                       for (i = 0; !found && i < SKYPIAX_MAX_INTERFACES; i++) {
+                               /* we've been asked for a normal interface name, or we have not found idle interfaces to serve as the "ANY" interface */
+                               if (strlen(globals.SKYPIAX_INTERFACES[i].name)
+                                       && (strncmp(globals.SKYPIAX_INTERFACES[i].name, argv[1], strlen(argv[1])) == 0)) {
+                                       globals.sk_console = &globals.SKYPIAX_INTERFACES[i];
+                                       stream->write_function(stream,
+                                                                                  "sk console is now: globals.SKYPIAX_INTERFACES[%d].name=|||%s|||\n", i, globals.SKYPIAX_INTERFACES[i].name);
+                                       stream->write_function(stream, "sk console is: |||%s|||\n", globals.sk_console->name);
+                                       found = 1;
+                                       break;
+                               }
+
+                       }
+                       if (!found)
+                               stream->write_function(stream, "ERROR: A Skypiax interface with name='%s' was not found\n", argv[1]);
+               } else {
+
+                       stream->write_function(stream, "-ERR Usage: sk console interface_name\n");
+                       goto end;
+               }
+
+       } else if (!strcasecmp(argv[0], "ciapalino")) {
+
+/* BEGIN: Changes heres */
+       } else if (!strcasecmp(argv[0], "reload")) {
+               if (load_config(SOFT_RELOAD) != SWITCH_STATUS_SUCCESS) {
+                       stream->write_function(stream, "sk reload failed\n");
+               } else {
+                       stream->write_function(stream, "sk reload success\n");
+               }
+       } else if (!strcasecmp(argv[0], "remove")) {
+               if (argc == 2) {
+                       if (remove_interface(argv[1]) == SWITCH_STATUS_SUCCESS) {
+                               if (interface_exists(argv[1]) == SWITCH_STATUS_SUCCESS) {
+                                       stream->write_function(stream, "sk remove '%s' failed\n", argv[1]);
+                               } else {
+                                       stream->write_function(stream, "sk remove '%s' success\n", argv[1]);
+                               }
+                       }
+               } else {
+                       stream->write_function(stream, "-ERR Usage: sk remove interface_name\n");
+                       goto end;
+               }
+/* END: Changes heres */
+
+       } else {
+               if (globals.sk_console)
+                       skypiax_signaling_write(globals.sk_console, (char *) cmd);
+               else
+                       stream->write_function(stream, "sk console is NOT yet assigned\n");
+       }
+  end:
+       switch_safe_free(mycmd);
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_STANDARD_API(skypiax_function)
+{
+       char *mycmd = NULL, *argv[10] = { 0 };
+       int argc = 0;
+       private_t *tech_pvt = NULL;
+
+       if (!zstr(cmd) && (mycmd = strdup(cmd))) {
+               argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+       }
+
+       if (!argc) {
+               stream->write_function(stream, "ERROR, usage: %s", SKYPIAX_SYNTAX);
+               goto end;
+       }
+
+       if (argc < 2) {
+               stream->write_function(stream, "ERROR, usage: %s", SKYPIAX_SYNTAX);
+               goto end;
+       }
+
+       if (argv[0]) {
+               int i;
+               int found = 0;
+
+               for (i = 0; !found && i < SKYPIAX_MAX_INTERFACES; i++) {
+                       /* we've been asked for a normal interface name, or we have not found idle interfaces to serve as the "ANY" interface */
+                       if (strlen(globals.SKYPIAX_INTERFACES[i].name)
+                               && (strncmp(globals.SKYPIAX_INTERFACES[i].name, argv[0], strlen(argv[0])) == 0)) {
+                               tech_pvt = &globals.SKYPIAX_INTERFACES[i];
+                               stream->write_function(stream, "Using interface: globals.SKYPIAX_INTERFACES[%d].name=|||%s|||\n", i, globals.SKYPIAX_INTERFACES[i].name);
+                               found = 1;
+                               break;
+                       }
+
+               }
+               if (!found) {
+                       stream->write_function(stream, "ERROR: A Skypiax interface with name='%s' was not found\n", argv[0]);
+                       switch_safe_free(mycmd);
+
+                       return SWITCH_STATUS_SUCCESS;
+               } else {
+                       skypiax_signaling_write(tech_pvt, (char *) &cmd[strlen(argv[0]) + 1]);
+               }
+       } else {
+               stream->write_function(stream, "ERROR, usage: %s", SKYPIAX_SYNTAX);
+       }
+  end:
+       switch_safe_free(mycmd);
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
+int skypiax_answer(private_t * tech_pvt, char *id, char *value)
+{
+       char msg_to_skype[1024];
+       int i;
+       int found = 0;
+       private_t *giovatech;
+       struct timeval timenow;
+
+       switch_mutex_lock(globals.mutex);
+
+       gettimeofday(&timenow, NULL);
+       for (i = 0; !found && i < SKYPIAX_MAX_INTERFACES; i++) {
+               if (strlen(globals.SKYPIAX_INTERFACES[i].name)) {
+
+                       giovatech = &globals.SKYPIAX_INTERFACES[i];
+                       //NOTICA("interface=%d, name=%s, giovatech->skype_call_id=%s, giovatech->interface_state=%d, giovatech->skype_user=%s, tech_pvt->skype_user=%s, giovatech->callid_number=%s, value=%s, delta=%ld  500000\n", SKYPIAX_P_LOG, i, giovatech->name, giovatech->skype_call_id, giovatech->interface_state, giovatech->skype_user, tech_pvt->skype_user, giovatech->callid_number, value, (((timenow.tv_sec - giovatech->answer_time.tv_sec) * 1000000) + (timenow.tv_usec - giovatech->answer_time.tv_usec)) );
+                       if (strlen(giovatech->skype_call_id) && (giovatech->interface_state != SKYPIAX_STATE_DOWN) && (!strcmp(giovatech->skype_user, tech_pvt->skype_user)) && (!strcmp(giovatech->callid_number, value)) && ((((timenow.tv_sec - giovatech->answer_time.tv_sec) * 1000000) + (timenow.tv_usec - giovatech->answer_time.tv_usec)) < 1000000)) {        //XXX 1.5sec - can have a max of 1 call coming from the same skypename to the same skypename each 1.5 seconds
+                               found = 1;
+                               DEBUGA_SKYPE
+                                       ("FOUND  (name=%s, giovatech->interface_state=%d != SKYPIAX_STATE_DOWN) && (giovatech->skype_user=%s == tech_pvt->skype_user=%s) && (giovatech->callid_number=%s == value=%s)\n",
+                                        SKYPIAX_P_LOG, giovatech->name, giovatech->interface_state,
+                                        giovatech->skype_user, tech_pvt->skype_user, giovatech->callid_number, value)
+                                       if (tech_pvt->interface_state == SKYPIAX_STATE_PRERING) {
+                                       tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                               } else if (tech_pvt->interface_state != 0 && tech_pvt->interface_state != SKYPIAX_STATE_DOWN) {
+                                       WARNINGA("Why an interface_state %d HERE?\n", SKYPIAX_P_LOG, tech_pvt->interface_state);
+                                       tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                               }
+
+                               break;
+                       }
+               }
+       }
+
+       if (found) {
+               //tech_pvt->callid_number[0]='\0';
+               //sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", id);
+               //skypiax_signaling_write(tech_pvt, msg_to_skype);
+               switch_mutex_unlock(globals.mutex);
+               return 0;
+       }
+       DEBUGA_SKYPE("NOT FOUND\n", SKYPIAX_P_LOG);
+
+       if (tech_pvt && tech_pvt->skype_call_id && !strlen(tech_pvt->skype_call_id)) {
+               /* we are not inside an active call */
+
+               tech_pvt->ib_calls++;
+
+               sprintf(msg_to_skype, "GET CALL %s PARTNER_DISPNAME", id);
+               skypiax_signaling_write(tech_pvt, msg_to_skype);
+               switch_sleep(10000);
+               tech_pvt->interface_state = SKYPIAX_STATE_PREANSWER;
+               sprintf(msg_to_skype, "ALTER CALL %s ANSWER", id);
+               skypiax_signaling_write(tech_pvt, msg_to_skype);
+               DEBUGA_SKYPE("We answered a Skype RING on skype_call %s\n", SKYPIAX_P_LOG, id);
+               //FIXME write a timestamp here
+               gettimeofday(&tech_pvt->answer_time, NULL);
+               switch_copy_string(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
+
+               switch_copy_string(tech_pvt->callid_number, value, sizeof(tech_pvt->callid_number) - 1);
+
+               DEBUGA_SKYPE
+                       ("NEW!  name: %s, state: %d, value=%s, tech_pvt->callid_number=%s, tech_pvt->skype_user=%s\n",
+                        SKYPIAX_P_LOG, tech_pvt->name, tech_pvt->interface_state, value, tech_pvt->callid_number, tech_pvt->skype_user);
+       } else if (!tech_pvt || !tech_pvt->skype_call_id) {
+               ERRORA("No Call ID?\n", SKYPIAX_P_LOG);
+       } else {
+               DEBUGA_SKYPE("We're in a call now (%s), let's refuse this one (%s)\n", SKYPIAX_P_LOG, tech_pvt->skype_call_id, id);
+               sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", id);
+               skypiax_signaling_write(tech_pvt, msg_to_skype);
+       }
+
+       switch_mutex_unlock(globals.mutex);
+       return 0;
+}
+int skypiax_transfer(private_t * tech_pvt, char *id, char *value)
+{
+       char msg_to_skype[1024];
+       int i;
+       int found = 0;
+       private_t *giovatech;
+       struct timeval timenow;
+
+       switch_mutex_lock(globals.mutex);
+
+       gettimeofday(&timenow, NULL);
+       for (i = 0; !found && i < SKYPIAX_MAX_INTERFACES; i++) {
+               if (strlen(globals.SKYPIAX_INTERFACES[i].name)) {
+
+                       giovatech = &globals.SKYPIAX_INTERFACES[i];
+                       //NOTICA("skype interface: %d, name: %s, state: %d, value=%s, giovatech->callid_number=%s, giovatech->skype_user=%s\n", SKYPIAX_P_LOG, i, giovatech->name, giovatech->interface_state, value, giovatech->callid_number, giovatech->skype_user);
+                       //FIXME check a timestamp here
+                       if (strlen(giovatech->skype_call_id) && (giovatech->interface_state != SKYPIAX_STATE_DOWN) && (!strcmp(giovatech->skype_user, tech_pvt->skype_user)) && (!strcmp(giovatech->callid_number, value)) && ((((timenow.tv_sec - giovatech->answer_time.tv_sec) * 1000000) + (timenow.tv_usec - giovatech->answer_time.tv_usec)) < 500000)) { //0.5sec
+                               found = 1;
+                               DEBUGA_SKYPE
+                                       ("FOUND  (name=%s, giovatech->interface_state=%d != SKYPIAX_STATE_DOWN) && (giovatech->skype_user=%s == tech_pvt->skype_user=%s) && (giovatech->callid_number=%s == value=%s)\n",
+                                        SKYPIAX_P_LOG, giovatech->name, giovatech->interface_state,
+                                        giovatech->skype_user, tech_pvt->skype_user, giovatech->callid_number, value)
+                                       break;
+                       }
+               }
+       }
+
+       if (found) {
+               //tech_pvt->callid_number[0]='\0';
+               //sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", id);
+               //skypiax_signaling_write(tech_pvt, msg_to_skype);
+               switch_mutex_unlock(globals.mutex);
+               return 0;
+       }
+       DEBUGA_SKYPE("NOT FOUND\n", SKYPIAX_P_LOG);
+
+       if (!tech_pvt || !tech_pvt->skype_call_id || !strlen(tech_pvt->skype_call_id)) {
+               /* we are not inside an active call */
+               DEBUGA_SKYPE("We're NO MORE in a call now %s\n", SKYPIAX_P_LOG, (tech_pvt && tech_pvt->skype_call_id) ? tech_pvt->skype_call_id : "");
+               switch_mutex_unlock(globals.mutex);
+
+       } else {
+
+               /* we're owned, we're in a call, let's try to transfer */
+               /************************** TODO
+                 Checking here if it is possible to transfer this call to Test2
+                 -> GET CALL 288 CAN_TRANSFER Test2
+                 <- CALL 288 CAN_TRANSFER test2 TRUE
+                **********************************/
+
+               private_t *available_skypiax_interface = NULL;
+
+               gettimeofday(&timenow, NULL);
+               for (i = 0; !found && i < SKYPIAX_MAX_INTERFACES; i++) {
+                       if (strlen(globals.SKYPIAX_INTERFACES[i].name)) {
+
+                               giovatech = &globals.SKYPIAX_INTERFACES[i];
+                               //NOTICA("skype interface: %d, name: %s, state: %d, value=%s, giovatech->callid_number=%s, giovatech->skype_user=%s\n", SKYPIAX_P_LOG, i, giovatech->name, giovatech->interface_state, value, giovatech->callid_number, giovatech->skype_user);
+                               //FIXME check a timestamp here
+                               if (strlen(giovatech->skype_transfer_call_id) && (giovatech->interface_state != SKYPIAX_STATE_DOWN) && (!strcmp(giovatech->skype_user, tech_pvt->skype_user)) && (!strcmp(giovatech->transfer_callid_number, value)) && ((((timenow.tv_sec - giovatech->transfer_time.tv_sec) * 1000000) + (timenow.tv_usec - giovatech->transfer_time.tv_usec)) < 1000000)) {  //1.0 sec
+                                       found = 1;
+                                       DEBUGA_SKYPE
+                                               ("FOUND  (name=%s, giovatech->interface_state=%d != SKYPIAX_STATE_DOWN) && (giovatech->skype_user=%s == tech_pvt->skype_user=%s) && (giovatech->transfer_callid_number=%s == value=%s)\n",
+                                                SKYPIAX_P_LOG, giovatech->name, giovatech->interface_state,
+                                                giovatech->skype_user, tech_pvt->skype_user, giovatech->transfer_callid_number, value)
+                                               break;
+                               }
+                       }
+               }
+
+               if (found) {
+                       //tech_pvt->callid_number[0]='\0';
+                       //sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", id);
+                       //skypiax_signaling_write(tech_pvt, msg_to_skype);
+                       switch_mutex_unlock(globals.mutex);
+                       return 0;
+               }
+               DEBUGA_SKYPE("NOT FOUND\n", SKYPIAX_P_LOG);
+
+               available_skypiax_interface = find_available_skypiax_interface_rr(tech_pvt);
+               if (available_skypiax_interface) {
+                       /* there is a skypiax interface idle, let's transfer the call to it */
+
+                       //FIXME write a timestamp here
+                       gettimeofday(&tech_pvt->transfer_time, NULL);
+                       switch_copy_string(tech_pvt->skype_transfer_call_id, id, sizeof(tech_pvt->skype_transfer_call_id) - 1);
+
+                       switch_copy_string(tech_pvt->transfer_callid_number, value, sizeof(tech_pvt->transfer_callid_number) - 1);
+
+                       DEBUGA_SKYPE
+                               ("Let's transfer the skype_call %s to %s interface (with skype_user: %s), because we are already in a skypiax call(%s)\n",
+                                SKYPIAX_P_LOG, tech_pvt->skype_call_id, available_skypiax_interface->name, available_skypiax_interface->skype_user, id);
+
+                       //FIXME why this? the inbound call will come, eventually, on that other interface
+                       //available_skypiax_interface->ib_calls++;
+
+                       sprintf(msg_to_skype, "ALTER CALL %s TRANSFER %s", id, available_skypiax_interface->skype_user);
+                       skypiax_signaling_write(tech_pvt, msg_to_skype);
+                       if (tech_pvt->interface_state == SKYPIAX_STATE_SELECTED) {
+                               tech_pvt->interface_state = SKYPIAX_STATE_IDLE; //we marked it SKYPIAX_STATE_SELECTED just in case it has to make an outbound call
+                       }
+               } else {
+                       /* no skypiax interfaces idle, do nothing */
+                       DEBUGA_SKYPE
+                               ("Not answering the skype_call %s, because we are already in a skypiax call(%s) and not transferring, because no other skypiax interfaces are available\n",
+                                SKYPIAX_P_LOG, id, tech_pvt->skype_call_id);
+                       sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", id);
+                       skypiax_signaling_write(tech_pvt, msg_to_skype);
+               }
+               switch_sleep(10000);
+               DEBUGA_SKYPE
+                       ("We have NOT answered a Skype RING from skype_call %s, because we are already in a skypiax call (%s)\n",
+                        SKYPIAX_P_LOG, id, tech_pvt->skype_call_id);
+
+               switch_mutex_unlock(globals.mutex);
+       }
+       return 0;
+}
+
+int incoming_chatmessage(private_t * tech_pvt, int which)
+{
+       switch_event_t *event;
+       switch_core_session_t *session = NULL;
+       int event_sent_to_esl = 0;
+
+       DEBUGA_SKYPE("received CHATMESSAGE on interface %s\n", SKYPIAX_P_LOG, tech_pvt->name);
+
+       if (!tech_pvt->report_incoming_chatmessages) {
+               DEBUGA_SKYPE("I will not generate an Event, report_incoming_chatmessages is %d\n", SKYPIAX_P_LOG, tech_pvt->report_incoming_chatmessages);
+               return 0;
+       }
+
+       if (!zstr(tech_pvt->session_uuid_str)) {
+               session = switch_core_session_locate(tech_pvt->session_uuid_str);
+       }
+       if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) {
+               switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", MDL_CHAT_PROTO);
+               switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", tech_pvt->name);
+               switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hint", tech_pvt->chatmessages[which].from_dispname);
+               switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", tech_pvt->chatmessages[which].from_handle);
+               switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "subject", "SIMPLE MESSAGE");
+               switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "chatname", tech_pvt->chatmessages[which].chatname);
+               switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "id", tech_pvt->chatmessages[which].id);
+               switch_event_add_body(event, "%s", tech_pvt->chatmessages[which].body);
+               if (session) {
+                       switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "during-call", "true");
+                       if (switch_core_session_queue_event(session, &event) != SWITCH_STATUS_SUCCESS) {
+                               switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "delivery-failure", "true");
+                               switch_event_fire(&event);
+                       }
+               } else {                                //no session
+                       switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "during-call", "false");
+                       switch_event_fire(&event);
+                       event_sent_to_esl = 1;
+               }
+
+       } else {
+               ERRORA("cannot create event on interface %s. WHY?????\n", SKYPIAX_P_LOG, tech_pvt->name);
+       }
+
+       if (!event_sent_to_esl) {
+
+               if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) {
+                       switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", MDL_CHAT_PROTO);
+                       switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", tech_pvt->name);
+                       switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hint", tech_pvt->chatmessages[which].from_dispname);
+                       switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", tech_pvt->chatmessages[which].from_handle);
+                       switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "subject", "SIMPLE MESSAGE");
+                       switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "chatname", tech_pvt->chatmessages[which].chatname);
+                       switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "id", tech_pvt->chatmessages[which].id);
+                       switch_event_add_body(event, "%s", tech_pvt->chatmessages[which].body);
+                       if (session) {
+                               switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "during-call", "true");
+                       } else {                        //no session
+                               switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "during-call", "false");
+                       }
+                       switch_event_fire(&event);
+               } else {
+                       ERRORA("cannot create event on interface %s. WHY?????\n", SKYPIAX_P_LOG, tech_pvt->name);
+               }
+       }
+
+       if (session) {
+               switch_core_session_rwunlock(session);
+       }
+       memset(&tech_pvt->chatmessages[which], '\0', sizeof(&tech_pvt->chatmessages[which]));
+       return 0;
+}
+
+
+SWITCH_STANDARD_API(skypiax_chat_function)
+{
+       char *mycmd = NULL, *argv[10] = { 0 };
+       int argc = 0;
+       private_t *tech_pvt = NULL;
+       //int tried =0;
+       int i;
+       int found = 0;
+       //char skype_msg[1024];
+
+       if (!zstr(cmd) && (mycmd = strdup(cmd))) {
+               argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+       }
+
+       if (!argc) {
+               stream->write_function(stream, "ERROR, usage: %s", SKYPIAX_CHAT_SYNTAX);
+               goto end;
+       }
+
+       if (argc < 3) {
+               stream->write_function(stream, "ERROR, usage: %s", SKYPIAX_CHAT_SYNTAX);
+               goto end;
+       }
+
+       if (argv[0]) {
+               for (i = 0; !found && i < SKYPIAX_MAX_INTERFACES; i++) {
+                       /* we've been asked for a normal interface name, or we have not found idle interfaces to serve as the "ANY" interface */
+                       if (strlen(globals.SKYPIAX_INTERFACES[i].name)
+                               && (strncmp(globals.SKYPIAX_INTERFACES[i].name, argv[0], strlen(argv[0])) == 0)) {
+                               tech_pvt = &globals.SKYPIAX_INTERFACES[i];
+                               stream->write_function(stream, "Using interface: globals.SKYPIAX_INTERFACES[%d].name=|||%s|||\n", i, globals.SKYPIAX_INTERFACES[i].name);
+                               found = 1;
+                               break;
+                       }
+
+               }
+               if (!found) {
+                       stream->write_function(stream, "ERROR: A Skypiax interface with name='%s' was not found\n", argv[0]);
+                       goto end;
+               } else {
+
+                       //chat_send(const char *proto, const char *from, const char *to, const char *subject, const char *body, const char *type, const char *hint);
+                       //chat_send(p*roto, const char *from, const char *to, const char *subject, const char *body, const char *type, const char *hint);
+                       //chat_send(MDL_CHAT_PROTO, tech_pvt->skype_user, argv[1], "SIMPLE MESSAGE", switch_str_nil((char *) &cmd[strlen(argv[0]) + 1 + strlen(argv[1]) + 1]), NULL, hint);
+
+                       NOTICA("chat_send(proto=%s, from=%s, to=%s, subject=%s, body=%s, type=NULL, hint=%s)\n", SKYPIAX_P_LOG, MDL_CHAT_PROTO, tech_pvt->skype_user,
+                                  argv[1], "SIMPLE MESSAGE", switch_str_nil((char *) &cmd[strlen(argv[0]) + 1 + strlen(argv[1]) + 1]), tech_pvt->name);
+
+                       chat_send(MDL_CHAT_PROTO, tech_pvt->skype_user, argv[1], "SIMPLE MESSAGE",
+                                         switch_str_nil((char *) &cmd[strlen(argv[0]) + 1 + strlen(argv[1]) + 1]), NULL, tech_pvt->name);
+
+                       //NOTICA("TEXT is: %s\n", SKYPIAX_P_LOG, (char *) &cmd[strlen(argv[0]) + 1 + strlen(argv[1]) + 1] );
+                       //snprintf(skype_msg, sizeof(skype_msg), "CHAT CREATE %s", argv[1]);
+                       //skypiax_signaling_write(tech_pvt, skype_msg);
+                       //switch_sleep(100);
+               }
+       } else {
+               stream->write_function(stream, "ERROR, usage: %s", SKYPIAX_CHAT_SYNTAX);
+               goto end;
+       }
+
+#ifdef NOTDEF
+
+       found = 0;
+
+       while (!found) {
+               for (i = 0; i < MAX_CHATS; i++) {
+                       if (!strcmp(tech_pvt->chats[i].dialog_partner, argv[1])) {
+                               snprintf(skype_msg, sizeof(skype_msg), "CHATMESSAGE %s %s", tech_pvt->chats[i].chatname,
+                                                (char *) &cmd[strlen(argv[0]) + 1 + strlen(argv[1]) + 1]);
+                               skypiax_signaling_write(tech_pvt, skype_msg);
+                               found = 1;
+                               break;
+                       }
+               }
+               if (found) {
+                       break;
+               }
+               if (tried > 1000) {
+                       stream->write_function(stream, "ERROR: no chat with dialog_partner='%s' was found\n", argv[1]);
+                       break;
+               }
+               switch_sleep(1000);
+       }
+#endif //NOTDEF
+
+  end:
+       switch_safe_free(mycmd);
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
+
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
+ */
diff --git a/src/mod/endpoints/mod_skypiax/109/skypiax.h b/src/mod/endpoints/mod_skypiax/109/skypiax.h
new file mode 100644 (file)
index 0000000..7ac7148
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II <anthmct@yahoo.com>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * This module (mod_skypiax) has been contributed by:
+ *
+ * Giovanni Maruzzelli (gmaruzz@gmail.com)
+ *
+ *
+ * Further Contributors:
+ *
+ *
+ * mod_skypiax.c -- Skype compatible Endpoint Module
+ *
+ */
+
+#include <switch.h>
+#include <switch_version.h>
+
+#ifndef WIN32
+#include <sys/time.h>
+#include <X11/Xlib.h>
+#include <X11/Xlibint.h>
+#include <X11/Xatom.h>
+#endif //WIN32
+
+#ifdef _MSC_VER
+//Windows macro  for FD_SET includes a warning C4127: conditional expression is constant
+#pragma warning(push)
+#pragma warning(disable:4127)
+#endif
+
+#define MY_EVENT_INCOMING_CHATMESSAGE "skypiax::incoming_chatmessage"
+
+#define SAMPLERATE_SKYPIAX 16000
+#define SAMPLES_PER_FRAME SAMPLERATE_SKYPIAX/50
+
+#ifndef SKYPIAX_SVN_VERSION
+#define SKYPIAX_SVN_VERSION SWITCH_VERSION_REVISION
+#endif /* SKYPIAX_SVN_VERSION */
+
+typedef enum {
+       TFLAG_IO = (1 << 0),
+       TFLAG_INBOUND = (1 << 1),
+       TFLAG_OUTBOUND = (1 << 2),
+       TFLAG_DTMF = (1 << 3),
+       TFLAG_VOICE = (1 << 4),
+       TFLAG_HANGUP = (1 << 5),
+       TFLAG_LINEAR = (1 << 6),
+       TFLAG_CODEC = (1 << 7),
+       TFLAG_BREAK = (1 << 8)
+} TFLAGS;
+
+typedef enum {
+       GFLAG_MY_CODEC_PREFS = (1 << 0)
+} GFLAGS;
+
+#define DEBUGA_SKYPE(...)  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,             "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_SKYPE  %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
+#define DEBUGA_CALL(...)  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,              "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_CALL  %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
+#define DEBUGA_PBX(...)  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,               "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_PBX  %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
+#define ERRORA(...)  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,           "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][ERRORA  %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
+#define WARNINGA(...)  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,               "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][WARNINGA  %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
+#define NOTICA(...)  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE,          "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][NOTICA  %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
+
+#define SKYPIAX_P_LOG NULL, (unsigned long)55, __LINE__, tech_pvt ? tech_pvt->name ? tech_pvt->name : "none" : "none", -1, tech_pvt ? tech_pvt->interface_state : -1, tech_pvt ? tech_pvt->skype_callflow : -1
+
+/*********************************/
+#define SKYPIAX_CAUSE_NORMAL           1
+/*********************************/
+#define SKYPIAX_FRAME_DTMF                     1
+/*********************************/
+#define SKYPIAX_CONTROL_RINGING                1
+#define SKYPIAX_CONTROL_ANSWER         2
+
+/*********************************/
+#define                SKYPIAX_STATE_IDLE                                      0
+#define                SKYPIAX_STATE_DOWN                                      1
+#define                SKYPIAX_STATE_RING                                      2
+#define                SKYPIAX_STATE_DIALING                           3
+#define                SKYPIAX_STATE_BUSY                                      4
+#define                SKYPIAX_STATE_UP                                        5
+#define                SKYPIAX_STATE_RINGING                           6
+#define                SKYPIAX_STATE_PRERING                           7
+#define                SKYPIAX_STATE_ERROR_DOUBLE_CALL         8
+#define                SKYPIAX_STATE_SELECTED                          9
+#define        SKYPIAX_STATE_HANGUP_REQUESTED          10
+#define                SKYPIAX_STATE_PREANSWER                         11
+/*********************************/
+/* call flow from the device */
+#define        CALLFLOW_CALL_IDLE                                      0
+#define        CALLFLOW_CALL_DOWN                                      1
+#define        CALLFLOW_INCOMING_RING                          2
+#define        CALLFLOW_CALL_DIALING                           3
+#define        CALLFLOW_CALL_LINEBUSY                          4
+#define        CALLFLOW_CALL_ACTIVE                            5
+#define        CALLFLOW_INCOMING_HANGUP                        6
+#define        CALLFLOW_CALL_RELEASED                          7
+#define        CALLFLOW_CALL_NOCARRIER                         8
+#define        CALLFLOW_CALL_INFLUX                            9
+#define        CALLFLOW_CALL_INCOMING                          10
+#define        CALLFLOW_CALL_FAILED                            11
+#define        CALLFLOW_CALL_NOSERVICE                         12
+#define        CALLFLOW_CALL_OUTGOINGRESTRICTED        13
+#define        CALLFLOW_CALL_SECURITYFAIL                      14
+#define        CALLFLOW_CALL_NOANSWER                          15
+#define        CALLFLOW_STATUS_FINISHED                        16
+#define        CALLFLOW_STATUS_CANCELLED                       17
+#define        CALLFLOW_STATUS_FAILED                          18
+#define        CALLFLOW_STATUS_REFUSED                         19
+#define        CALLFLOW_STATUS_RINGING                         20
+#define        CALLFLOW_STATUS_INPROGRESS                      21
+#define        CALLFLOW_STATUS_UNPLACED                        22
+#define        CALLFLOW_STATUS_ROUTING                         23
+#define        CALLFLOW_STATUS_EARLYMEDIA                      24
+#define        CALLFLOW_INCOMING_CALLID                        25
+#define        CALLFLOW_STATUS_REMOTEHOLD                      26
+
+/*********************************/
+
+#define SKYPIAX_MAX_INTERFACES 64
+
+#ifndef WIN32
+struct SkypiaxHandles {
+       Window skype_win;
+       Display *disp;
+       Window win;
+       int currentuserhandle;
+       int api_connected;
+       int fdesc[2];
+};
+#else //WIN32
+
+struct SkypiaxHandles {
+       HWND win32_hInit_MainWindowHandle;
+       HWND win32_hGlobal_SkypeAPIWindowHandle;
+       HINSTANCE win32_hInit_ProcessHandle;
+       char win32_acInit_WindowClassName[128];
+       UINT win32_uiGlobal_MsgID_SkypeControlAPIAttach;
+       UINT win32_uiGlobal_MsgID_SkypeControlAPIDiscover;
+       int currentuserhandle;
+       int api_connected;
+       switch_file_t *fdesc[2];
+};
+#endif //WIN32
+
+#define MAX_CHATS 10
+
+struct chat {
+       char chatname[256];
+       char dialog_partner[256];
+};
+typedef struct chat chat_t;
+
+#define MAX_CHATMESSAGES 10
+
+struct chatmessage {
+       char id[256];
+       char type[256];
+       char chatname[256];
+       char from_handle[256];
+       char from_dispname[256];
+       char body[512];
+};
+typedef struct chatmessage chatmessage_t;
+struct private_object {
+       unsigned int flags;
+       switch_codec_t read_codec;
+       switch_codec_t write_codec;
+       switch_frame_t read_frame;
+       unsigned char databuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
+       char session_uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
+       switch_caller_profile_t *caller_profile;
+       switch_mutex_t *mutex;
+       switch_mutex_t *flag_mutex;
+
+       char interface_id[80];
+       char name[80];
+       char dialplan[80];
+       char context[80];
+       char dial_regex[256];
+       char fail_dial_regex[256];
+       char hold_music[256];
+       char type[256];
+       char X11_display[256];
+#ifdef WIN32
+       unsigned short tcp_cli_port;
+       unsigned short tcp_srv_port;
+#else
+       int tcp_cli_port;
+       int tcp_srv_port;
+#endif
+       struct SkypiaxHandles SkypiaxHandles;
+
+       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 */
+       char callid_name[50];
+       char callid_number[50];
+       double playback_boost;
+       double capture_boost;
+       int stripmsd;
+       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;
+#ifdef WIN32
+       switch_file_t *audiopipe_srv[2];
+       switch_file_t *audiopipe_cli[2];
+       switch_file_t *skypiax_sound_capt_fd;   /*!< \brief file descriptor for sound capture dev */
+#else                                                  /* WIN32 */
+       int audiopipe_srv[2];
+       int audiopipe_cli[2];
+       int skypiax_sound_capt_fd;      /*!< \brief file descriptor for sound capture dev */
+#endif                                                 /* WIN32 */
+       switch_thread_t *tcp_srv_thread;
+       switch_thread_t *tcp_cli_thread;
+       switch_thread_t *skypiax_signaling_thread;
+       switch_thread_t *skypiax_api_thread;
+       short audiobuf[SAMPLES_PER_FRAME];
+       int audiobuf_is_loaded;
+       short audiobuf_cli[SAMPLES_PER_FRAME];
+       switch_mutex_t *mutex_audio_cli;
+       int flag_audio_cli;
+       short audiobuf_srv[SAMPLES_PER_FRAME];
+       switch_mutex_t *mutex_audio_srv;
+       int flag_audio_srv;
+
+       //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;
+       char skype_user[256];
+       char skype_password[256];
+       char destination[256];
+       struct timeval answer_time;
+
+       struct timeval transfer_time;
+       char transfer_callid_number[50];
+       char skype_transfer_call_id[512];
+       int running;
+       uint32_t ib_calls;
+       uint32_t ob_calls;
+       uint32_t ib_failed_calls;
+       uint32_t ob_failed_calls;
+
+       chatmessage_t chatmessages[MAX_CHATMESSAGES];
+       chat_t chats[MAX_CHATS];
+       uint32_t report_incoming_chatmessages;
+       switch_timer_t timer_read;
+       switch_timer_t timer_write;
+};
+
+typedef struct private_object private_t;
+
+void *SWITCH_THREAD_FUNC skypiax_api_thread_func(switch_thread_t * thread, void *obj);
+int skypiax_audio_read(private_t * tech_pvt);
+int skypiax_audio_init(private_t * tech_pvt);
+int skypiax_signaling_write(private_t * tech_pvt, char *msg_to_skype);
+int skypiax_signaling_read(private_t * tech_pvt);
+
+int skypiax_call(private_t * tech_pvt, char *idest, int timeout);
+int skypiax_senddigit(private_t * tech_pvt, char digit);
+
+void *skypiax_do_tcp_srv_thread_func(void *obj);
+void *SWITCH_THREAD_FUNC skypiax_do_tcp_srv_thread(switch_thread_t * thread, void *obj);
+
+void *skypiax_do_tcp_cli_thread_func(void *obj);
+void *SWITCH_THREAD_FUNC skypiax_do_tcp_cli_thread(switch_thread_t * thread, void *obj);
+
+void *skypiax_do_skypeapi_thread_func(void *obj);
+void *SWITCH_THREAD_FUNC skypiax_do_skypeapi_thread(switch_thread_t * thread, void *obj);
+int dtmf_received(private_t * tech_pvt, char *value);
+int start_audio_threads(private_t * tech_pvt);
+int new_inbound_channel(private_t * tech_pvt);
+int outbound_channel_answered(private_t * tech_pvt);
+int skypiax_signaling_write(private_t * tech_pvt, char *msg_to_skype);
+#if defined(WIN32) && !defined(__CYGWIN__)
+int skypiax_pipe_read(switch_file_t * pipe, short *buf, int howmany);
+int skypiax_pipe_write(switch_file_t * pipe, short *buf, int howmany);
+/* Visual C do not have strsep ? */
+char *strsep(char **stringp, const char *delim);
+#else
+int skypiax_pipe_read(int pipe, short *buf, int howmany);
+int skypiax_pipe_write(int pipe, short *buf, int howmany);
+#endif /* WIN32 */
+int skypiax_close_socket(unsigned int fd);
+private_t *find_available_skypiax_interface_rr(private_t * tech_pvt_calling);
+int remote_party_is_ringing(private_t * tech_pvt);
+int remote_party_is_early_media(private_t * tech_pvt);
+int skypiax_answer(private_t * tech_pvt, char *id, char *value);
+int skypiax_transfer(private_t * tech_pvt, char *id, char *value);
+#ifndef WIN32
+int skypiax_socket_create_and_bind(private_t * tech_pvt, int *which_port);
+#else
+int skypiax_socket_create_and_bind(private_t * tech_pvt, unsigned short *which_port);
+#endif //WIN32
+int incoming_chatmessage(private_t * tech_pvt, int which);
diff --git a/src/mod/endpoints/mod_skypiax/109/skypiax_protocol.c b/src/mod/endpoints/mod_skypiax/109/skypiax_protocol.c
new file mode 100644 (file)
index 0000000..d869030
--- /dev/null
@@ -0,0 +1,1947 @@
+#include "skypiax.h"
+
+#ifdef ASTERISK
+#define skypiax_sleep usleep
+#define skypiax_strncpy strncpy
+#define tech_pvt p
+extern int skypiax_debug;
+extern char *skypiax_console_active;
+#else /* FREESWITCH */
+#define skypiax_sleep switch_sleep
+#define skypiax_strncpy switch_copy_string
+extern switch_memory_pool_t *skypiax_module_pool;
+extern switch_endpoint_interface_t *skypiax_endpoint_interface;
+#endif /* ASTERISK */
+int samplerate_skypiax = SAMPLERATE_SKYPIAX;
+
+extern int running;
+
+/*************************************/
+/* suspicious globals FIXME */
+#ifdef WIN32
+DWORD win32_dwThreadId;
+#else
+XErrorHandler old_handler = 0;
+int xerror = 0;
+#endif /* WIN32 */
+/*************************************/
+#ifndef WIN32
+int skypiax_socket_create_and_bind(private_t * tech_pvt, int *which_port)
+#else
+int skypiax_socket_create_and_bind(private_t * tech_pvt, unsigned short *which_port)
+#endif                                                 //WIN32
+{
+       int s = -1;
+       struct sockaddr_in my_addr;
+#ifndef WIN32
+       int start_port = 6001;
+#else
+       unsigned short start_port = 6001;
+#endif //WIN32
+       int sockbufsize = 0;
+       unsigned int size = sizeof(int);
+
+
+       memset(&my_addr, 0, sizeof(my_addr));
+       my_addr.sin_family = AF_INET;
+       my_addr.sin_addr.s_addr = htonl(0x7f000001);    /* use the localhost */
+
+       if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+               ERRORA("socket Error\n", SKYPIAX_P_LOG);
+               return -1;
+       }
+
+       if (*which_port != 0)
+               start_port = *which_port;
+
+       my_addr.sin_port = htons(start_port);
+       //fcntl(s, F_SETFL, O_NONBLOCK);
+       //tech_pvt->tcp_cli_port = start_port;
+       *which_port = start_port;
+       while (bind(s, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) < 0) {
+               DEBUGA_SKYPE("*which_port=%d, tech_pvt->tcp_cli_port=%d, tech_pvt->tcp_srv_port=%d\n", SKYPIAX_P_LOG, *which_port, tech_pvt->tcp_cli_port,
+                                        tech_pvt->tcp_srv_port);
+               DEBUGA_SKYPE("bind errno=%d, error: %s\n", SKYPIAX_P_LOG, errno, strerror(errno));
+               start_port++;
+               my_addr.sin_port = htons(start_port);
+               *which_port = start_port;
+               DEBUGA_SKYPE("*which_port=%d, tech_pvt->tcp_cli_port=%d, tech_pvt->tcp_srv_port=%d\n", SKYPIAX_P_LOG, *which_port, tech_pvt->tcp_cli_port,
+                                        tech_pvt->tcp_srv_port);
+
+               if (start_port > 65000) {
+                       ERRORA("NO MORE PORTS! *which_port=%d, tech_pvt->tcp_cli_port=%d, tech_pvt->tcp_srv_port=%d\n", SKYPIAX_P_LOG, *which_port,
+                                  tech_pvt->tcp_cli_port, tech_pvt->tcp_srv_port);
+                       return -1;
+               }
+       }
+
+       DEBUGA_SKYPE("SUCCESS! *which_port=%d, tech_pvt->tcp_cli_port=%d, tech_pvt->tcp_srv_port=%d\n", SKYPIAX_P_LOG, *which_port, tech_pvt->tcp_cli_port,
+                                tech_pvt->tcp_srv_port);
+
+       sockbufsize = 0;
+       size = sizeof(int);
+       getsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *) &sockbufsize, &size);
+       DEBUGA_SKYPE("1 SO_RCVBUF is %d, size is %d\n", SKYPIAX_P_LOG, sockbufsize, size);
+       sockbufsize = 0;
+       size = sizeof(int);
+       getsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *) &sockbufsize, &size);
+       DEBUGA_SKYPE("1 SO_SNDBUF is %d, size is %d\n", SKYPIAX_P_LOG, sockbufsize, size);
+
+
+
+/* for virtual machines, eg: Linux domU-12-31-39-02-68-28 2.6.18-xenU-ec2-v1.0 #2 SMP Tue Feb 19 10:51:53 EST 2008 i686 athlon i386 GNU/Linux
+ * use:
+ * sockbufsize=SAMPLES_PER_FRAME * 8;
+ */
+#ifdef WIN32
+       sockbufsize = SAMPLES_PER_FRAME * 8 * 3;
+#else
+       sockbufsize = SAMPLES_PER_FRAME * 8;
+#endif //WIN32
+       size = sizeof(int);
+       setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *) &sockbufsize, size);
+
+       sockbufsize = 0;
+       size = sizeof(int);
+       getsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *) &sockbufsize, &size);
+       DEBUGA_SKYPE("2 SO_RCVBUF is %d, size is %d\n", SKYPIAX_P_LOG, sockbufsize, size);
+
+/* for virtual machines, eg: Linux domU-12-31-39-02-68-28 2.6.18-xenU-ec2-v1.0 #2 SMP Tue Feb 19 10:51:53 EST 2008 i686 athlon i386 GNU/Linux
+ * use:
+ * sockbufsize=SAMPLES_PER_FRAME * 8;
+ */
+#ifdef WIN32
+       sockbufsize = SAMPLES_PER_FRAME * 8 * 3;
+#else
+       sockbufsize = SAMPLES_PER_FRAME * 8;
+#endif //WIN32
+       size = sizeof(int);
+       setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *) &sockbufsize, size);
+
+       sockbufsize = 0;
+       size = sizeof(int);
+       getsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *) &sockbufsize, &size);
+       DEBUGA_SKYPE("2 SO_SNDBUF is %d, size is %d\n", SKYPIAX_P_LOG, sockbufsize, size);
+
+
+
+       return s;
+}
+
+int skypiax_signaling_read(private_t * tech_pvt)
+{
+       char read_from_pipe[4096];
+       char message[4096];
+       char message_2[4096];
+       char *buf, obj[512] = "", id[512] = "", prop[512] = "", value[512] = "", *where;
+       char **stringp = NULL;
+       int a;
+       unsigned int howmany;
+       unsigned int i;
+
+       memset(read_from_pipe, 0, 4096);
+       memset(message, 0, 4096);
+       memset(message_2, 0, 4096);
+
+       howmany = skypiax_pipe_read(tech_pvt->SkypiaxHandles.fdesc[0], (short *) read_from_pipe, sizeof(read_from_pipe));
+
+       a = 0;
+       for (i = 0; i < howmany; i++) {
+               message[a] = read_from_pipe[i];
+               a++;
+
+               if (read_from_pipe[i] == '\0') {
+
+                       //if (!strstr(message, "DURATION")) {
+                       DEBUGA_SKYPE("READING: |||%s||| \n", SKYPIAX_P_LOG, message);
+                       //}
+
+                       if (!strcasecmp(message, "ERROR 68")) {
+                               DEBUGA_SKYPE
+                                       ("If I don't connect immediately, please give the Skype client authorization to be connected by Skypiax (and to not ask you again)\n",
+                                        SKYPIAX_P_LOG);
+                               skypiax_sleep(1000000);
+                               skypiax_signaling_write(tech_pvt, "PROTOCOL 7");
+                               skypiax_sleep(10000);
+                               return 0;
+                       }
+                       if (!strncasecmp(message, "ERROR 92 CALL", 12)) {
+                               ERRORA("Skype got ERROR: |||%s|||, the (skypeout) number we called was not recognized as valid\n", SKYPIAX_P_LOG, message);
+                               tech_pvt->skype_callflow = CALLFLOW_STATUS_FINISHED;
+                               DEBUGA_SKYPE("skype_call now is DOWN\n", SKYPIAX_P_LOG);
+                               tech_pvt->skype_call_id[0] = '\0';
+
+                               if (tech_pvt->interface_state != SKYPIAX_STATE_HANGUP_REQUESTED) {
+                                       tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                       return CALLFLOW_INCOMING_HANGUP;
+                               } else {
+                                       tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                               }
+                       }
+
+                       if (!strncasecmp(message, "ERROR", 4)) {
+                               if (!strncasecmp(message, "ERROR 96 CALL", 12)) {
+                                       DEBUGA_SKYPE
+                                               ("Skype got ERROR: |||%s|||, we are trying to use this interface to make or receive a call, but another call is half-active on this interface. Let's the previous one to continue.\n",
+                                                SKYPIAX_P_LOG, message);
+                               } else if (!strncasecmp(message, "ERROR 99 CALL", 12)) {
+                                       ERRORA("Skype got ERROR: |||%s|||, another call is active on this interface\n\n\n", SKYPIAX_P_LOG, message);
+                                       tech_pvt->interface_state = SKYPIAX_STATE_ERROR_DOUBLE_CALL;
+                               } else if (!strncasecmp(message, "ERROR 592 ALTER CALL", 19)) {
+                                       ERRORA("Skype got ERROR about TRANSFERRING, no problem: |||%s|||\n", SKYPIAX_P_LOG, message);
+                               } else if (!strncasecmp(message, "ERROR 559 CALL", 13)) {
+                                       DEBUGA_SKYPE("Skype got ERROR about a failed action (probably TRYING to HANGUP A CALL), no problem: |||%s|||\n", SKYPIAX_P_LOG,
+                                                                message);
+                               } else {
+                                       ERRORA("Skype got ERROR: |||%s|||\n", SKYPIAX_P_LOG, message);
+                                       tech_pvt->skype_callflow = CALLFLOW_STATUS_FINISHED;
+                                       ERRORA("skype_call now is DOWN\n", SKYPIAX_P_LOG);
+                                       tech_pvt->skype_call_id[0] = '\0';
+
+                                       if (tech_pvt->interface_state != SKYPIAX_STATE_HANGUP_REQUESTED) {
+                                               tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                               return CALLFLOW_INCOMING_HANGUP;
+                                       } else {
+                                               tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                       }
+                               }
+                       }
+
+
+
+
+                       skypiax_strncpy(message_2, message, sizeof(message) - 1);
+                       buf = message;
+                       stringp = &buf;
+                       where = strsep(stringp, " ");
+                       if (!where) {
+                               WARNINGA("Skype MSG without spaces: %s\n", SKYPIAX_P_LOG, message);
+                       }
+
+
+
+
+
+
+
+
+                       if (!strcasecmp(message, "CURRENTUSERHANDLE")) {
+                               skypiax_strncpy(obj, where, sizeof(obj) - 1);
+                               where = strsep(stringp, " ");
+                               skypiax_strncpy(id, where, sizeof(id) - 1);
+                               if (!strcasecmp(id, tech_pvt->skype_user)) {
+                                       tech_pvt->SkypiaxHandles.currentuserhandle = 1;
+                                       DEBUGA_SKYPE
+                                               ("Skype MSG: message: %s, currentuserhandle: %s, cuh: %s, skype_user: %s!\n",
+                                                SKYPIAX_P_LOG, message, obj, id, tech_pvt->skype_user);
+                               }
+                       }
+                       if (!strcasecmp(message, "USER")) {
+                               skypiax_strncpy(obj, where, sizeof(obj) - 1);
+                               where = strsep(stringp, " ");
+                               skypiax_strncpy(id, where, sizeof(id) - 1);
+                               where = strsep(stringp, " ");
+                               skypiax_strncpy(prop, where, sizeof(prop) - 1);
+                               if (!strcasecmp(prop, "RECEIVEDAUTHREQUEST")) {
+                                       char msg_to_skype[256];
+                                       DEBUGA_SKYPE("Skype MSG: message: %s, obj: %s, id: %s, prop: %s!\n", SKYPIAX_P_LOG, message, obj, id, prop);
+                                       //TODO: allow authorization based on config param
+                                       sprintf(msg_to_skype, "SET USER %s ISAUTHORIZED TRUE", id);
+                                       skypiax_signaling_write(tech_pvt, msg_to_skype);
+                               }
+                       }
+                       if (!strcasecmp(message, "MESSAGE")) {
+                               skypiax_strncpy(obj, where, sizeof(obj) - 1);
+                               where = strsep(stringp, " ");
+                               skypiax_strncpy(id, where, sizeof(id) - 1);
+                               where = strsep(stringp, " ");
+                               skypiax_strncpy(prop, where, sizeof(prop) - 1);
+                               if (!strcasecmp(prop, "STATUS")) {
+                                       where = strsep(stringp, " ");
+                                       skypiax_strncpy(value, where, sizeof(value) - 1);
+                                       if (!strcasecmp(value, "RECEIVED")) {
+                                               char msg_to_skype[256];
+                                               DEBUGA_SKYPE("Skype MSG: message: %s, obj: %s, id: %s, prop: %s value: %s!\n", SKYPIAX_P_LOG, message, obj, id, prop, value);
+                                               //TODO: authomatically flag messages as read based on config param
+                                               sprintf(msg_to_skype, "SET MESSAGE %s SEEN", id);
+                                               skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                       }
+                               } else if (!strcasecmp(prop, "BODY")) {
+                                       char msg_to_skype[256];
+                                       DEBUGA_SKYPE("Skype MSG: message: %s, obj: %s, id: %s, prop: %s!\n", SKYPIAX_P_LOG, message, obj, id, prop);
+                                       //TODO: authomatically flag messages as read based on config param
+                                       sprintf(msg_to_skype, "SET MESSAGE %s SEEN", id);
+                                       skypiax_signaling_write(tech_pvt, msg_to_skype);
+                               }
+                       }
+                       if (!strcasecmp(message, "CHAT")) {
+                               char msg_to_skype[256];
+                               int i;
+                               int found;
+
+                               skypiax_strncpy(obj, where, sizeof(obj) - 1);
+                               where = strsep(stringp, " ");
+                               skypiax_strncpy(id, where, sizeof(id) - 1);
+                               where = strsep(stringp, " ");
+                               skypiax_strncpy(prop, where, sizeof(prop) - 1);
+                               skypiax_strncpy(value, *stringp, sizeof(value) - 1);
+
+                               if (!strcasecmp(prop, "STATUS") && !strcasecmp(value, "DIALOG")) {
+                                       DEBUGA_SKYPE("CHAT %s is DIALOG\n", SKYPIAX_P_LOG, id);
+                                       sprintf(msg_to_skype, "GET CHAT %s DIALOG_PARTNER", id);
+                                       skypiax_signaling_write(tech_pvt, msg_to_skype);
+                               }
+
+                               if (!strcasecmp(prop, "DIALOG_PARTNER")) {
+                                       DEBUGA_SKYPE("CHAT %s has DIALOG_PARTNER %s\n", SKYPIAX_P_LOG, id, value);
+                                       found = 0;
+                                       for (i = 0; i < MAX_CHATS; i++) {
+                                               if (strlen(tech_pvt->chats[i].chatname) == 0 || !strcmp(tech_pvt->chats[i].chatname, id)) {
+                                                       strncpy(tech_pvt->chats[i].chatname, id, sizeof(tech_pvt->chats[i].chatname));
+                                                       strncpy(tech_pvt->chats[i].dialog_partner, value, sizeof(tech_pvt->chats[i].dialog_partner));
+                                                       found = 1;
+                                                       break;
+                                               }
+                                       }
+                                       if (!found) {
+                                               DEBUGA_SKYPE("why we do not have a chats slot free? we have more than %d chats in parallel?\n", SKYPIAX_P_LOG, MAX_CHATS);
+                                       }
+
+                                       DEBUGA_SKYPE("CHAT %s is in position %d in the chats array, chatname=%s, dialog_partner=%s\n", SKYPIAX_P_LOG, id, i,
+                                                                tech_pvt->chats[i].chatname, tech_pvt->chats[i].dialog_partner);
+                               }
+
+                       }
+
+
+                       if (!strcasecmp(message, "CHATMESSAGE")) {
+                               char msg_to_skype[256];
+                               int i;
+                               int found;
+
+                               skypiax_strncpy(obj, where, sizeof(obj) - 1);
+                               where = strsep(stringp, " ");
+                               skypiax_strncpy(id, where, sizeof(id) - 1);
+                               where = strsep(stringp, " ");
+                               skypiax_strncpy(prop, where, sizeof(prop) - 1);
+                               skypiax_strncpy(value, *stringp, sizeof(value) - 1);
+
+                               if (!strcasecmp(prop, "STATUS") && !strcasecmp(value, "RECEIVED")) {
+                                       DEBUGA_SKYPE("RECEIVED CHATMESSAGE %s, let's see which type it is\n", SKYPIAX_P_LOG, id);
+                                       sprintf(msg_to_skype, "GET CHATMESSAGE %s TYPE", id);
+                                       skypiax_signaling_write(tech_pvt, msg_to_skype);
+                               }
+
+                               if (!strcasecmp(prop, "TYPE") && !strcasecmp(value, "SAID")) {
+                                       DEBUGA_SKYPE("CHATMESSAGE %s is of type SAID, let's get the other infos\n", SKYPIAX_P_LOG, id);
+                                       found = 0;
+                                       for (i = 0; i < MAX_CHATMESSAGES; i++) {
+                                               if (strlen(tech_pvt->chatmessages[i].id) == 0) {
+                                                       strncpy(tech_pvt->chatmessages[i].id, id, sizeof(tech_pvt->chatmessages[i].id));
+                                                       strncpy(tech_pvt->chatmessages[i].type, value, sizeof(tech_pvt->chatmessages[i].type));
+                                                       found = 1;
+                                                       break;
+                                               }
+                                       }
+                                       if (!found) {
+                                               DEBUGA_SKYPE("why we do not have a chatmessages slot free? we have more than %d chatmessages in parallel?\n", SKYPIAX_P_LOG,
+                                                                        MAX_CHATMESSAGES);
+                                       } else {
+                                               DEBUGA_SKYPE("CHATMESSAGE %s is in position %d in the chatmessages array, type=%s, id=%s\n", SKYPIAX_P_LOG, id, i,
+                                                                        tech_pvt->chatmessages[i].type, tech_pvt->chatmessages[i].id);
+                                               sprintf(msg_to_skype, "GET CHATMESSAGE %s CHATNAME", id);
+                                               skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                               skypiax_sleep(1000);
+                                               sprintf(msg_to_skype, "GET CHATMESSAGE %s FROM_HANDLE", id);
+                                               skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                               skypiax_sleep(1000);
+                                               sprintf(msg_to_skype, "GET CHATMESSAGE %s FROM_DISPNAME", id);
+                                               skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                               skypiax_sleep(1000);
+                                               sprintf(msg_to_skype, "GET CHATMESSAGE %s BODY", id);
+                                               skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                       }
+                               }
+
+                               if (!strcasecmp(prop, "CHATNAME")) {
+                                       DEBUGA_SKYPE("CHATMESSAGE %s belongs to the CHAT %s\n", SKYPIAX_P_LOG, id, value);
+                                       found = 0;
+                                       for (i = 0; i < MAX_CHATMESSAGES; i++) {
+                                               if (!strcmp(tech_pvt->chatmessages[i].id, id)) {
+                                                       strncpy(tech_pvt->chatmessages[i].chatname, value, sizeof(tech_pvt->chatmessages[i].chatname));
+                                                       found = 1;
+                                                       break;
+                                               }
+                                       }
+                                       if (!found) {
+                                               DEBUGA_SKYPE("why chatmessage %s was not found in the chatmessages array??\n", SKYPIAX_P_LOG, id);
+                                       }
+                               }
+                               if (!strcasecmp(prop, "FROM_HANDLE")) {
+                                       DEBUGA_SKYPE("CHATMESSAGE %s was sent by FROM_HANDLE %s\n", SKYPIAX_P_LOG, id, value);
+                                       found = 0;
+                                       for (i = 0; i < MAX_CHATMESSAGES; i++) {
+                                               if (!strcmp(tech_pvt->chatmessages[i].id, id)) {
+                                                       strncpy(tech_pvt->chatmessages[i].from_handle, value, sizeof(tech_pvt->chatmessages[i].from_handle));
+                                                       found = 1;
+                                                       break;
+                                               }
+                                       }
+                                       if (!found) {
+                                               DEBUGA_SKYPE("why chatmessage %s was not found in the chatmessages array??\n", SKYPIAX_P_LOG, id);
+                                       }
+
+                               }
+                               if (!strcasecmp(prop, "FROM_DISPNAME")) {
+                                       DEBUGA_SKYPE("CHATMESSAGE %s was sent by FROM_DISPNAME %s\n", SKYPIAX_P_LOG, id, value);
+                                       found = 0;
+                                       for (i = 0; i < MAX_CHATMESSAGES; i++) {
+                                               if (!strcmp(tech_pvt->chatmessages[i].id, id)) {
+                                                       strncpy(tech_pvt->chatmessages[i].from_dispname, value, sizeof(tech_pvt->chatmessages[i].from_dispname));
+                                                       found = 1;
+                                                       break;
+                                               }
+                                       }
+                                       if (!found) {
+                                               DEBUGA_SKYPE("why chatmessage %s was not found in the chatmessages array??\n", SKYPIAX_P_LOG, id);
+                                       }
+
+                               }
+                               if (!strcasecmp(prop, "BODY")) {
+                                       DEBUGA_SKYPE("CHATMESSAGE %s has BODY %s\n", SKYPIAX_P_LOG, id, value);
+                                       found = 0;
+                                       for (i = 0; i < MAX_CHATMESSAGES; i++) {
+                                               if (!strcmp(tech_pvt->chatmessages[i].id, id)) {
+                                                       strncpy(tech_pvt->chatmessages[i].body, value, sizeof(tech_pvt->chatmessages[i].body));
+                                                       found = 1;
+                                                       break;
+                                               }
+                                       }
+                                       if (!found) {
+                                               DEBUGA_SKYPE("why chatmessage %s was not found in the chatmessages array??\n", SKYPIAX_P_LOG, id);
+                                       } else {
+                                               DEBUGA_SKYPE
+                                                       ("CHATMESSAGE %s is in position %d in the chatmessages array, type=%s, id=%s, chatname=%s, from_handle=%s, from_dispname=%s, body=%s\n",
+                                                        SKYPIAX_P_LOG, id, i, tech_pvt->chatmessages[i].type, tech_pvt->chatmessages[i].id, tech_pvt->chatmessages[i].chatname,
+                                                        tech_pvt->chatmessages[i].from_handle, tech_pvt->chatmessages[i].from_dispname, tech_pvt->chatmessages[i].body);
+                                               if (strcmp(tech_pvt->chatmessages[i].from_handle, tech_pvt->skype_user)) {      //if the message was not sent by myself
+                                                       incoming_chatmessage(tech_pvt, i);
+                                               }
+                                       }
+
+                               }
+
+                       }
+
+
+                       if (!strcasecmp(message, "CALL")) {
+                               skypiax_strncpy(obj, where, sizeof(obj) - 1);
+                               where = strsep(stringp, " ");
+                               skypiax_strncpy(id, where, sizeof(id) - 1);
+                               where = strsep(stringp, " ");
+                               skypiax_strncpy(prop, where, sizeof(prop) - 1);
+                               where = strsep(stringp, " ");
+                               skypiax_strncpy(value, where, sizeof(value) - 1);
+                               where = strsep(stringp, " ");
+
+                               //DEBUGA_SKYPE
+                               //("Skype MSG: message: %s, obj: %s, id: %s, prop: %s, value: %s,where: %s!\n",
+                               //SKYPIAX_P_LOG, message, obj, id, prop, value, where ? where : "NULL");
+
+                               if (!strcasecmp(prop, "PARTNER_HANDLE")) {
+                                       if (tech_pvt->interface_state != SKYPIAX_STATE_SELECTED && (!strlen(tech_pvt->skype_call_id) || !strlen(tech_pvt->session_uuid_str))) {
+                                               /* we are NOT inside an active call */
+                                               DEBUGA_SKYPE("Call %s TRY ANSWER\n", SKYPIAX_P_LOG, id);
+                                               skypiax_answer(tech_pvt, id, value);
+                                       } else {
+                                               /* we are inside an active call */
+                                               if (!strcasecmp(tech_pvt->skype_call_id, id)) {
+                                                       /* this is the call in which we are calling out */
+                                                       DEBUGA_SKYPE("Call %s DO NOTHING\n", SKYPIAX_P_LOG, id);
+                                               } else {
+                                                       skypiax_sleep(400000);  //0.4 seconds
+                                                       DEBUGA_SKYPE("Call %s TRY TRANSFER\n", SKYPIAX_P_LOG, id);
+                                                       skypiax_transfer(tech_pvt, id, value);
+                                               }
+                                       }
+                               }
+                               if (!strcasecmp(prop, "PARTNER_DISPNAME")) {
+                                       snprintf(tech_pvt->callid_name, sizeof(tech_pvt->callid_name) - 1, "%s%s%s", value, where ? " " : "", where ? where : "");
+                                       //DEBUGA_SKYPE
+                                       //("the skype_call %s caller PARTNER_DISPNAME (tech_pvt->callid_name) is: %s\n",
+                                       //SKYPIAX_P_LOG, id, tech_pvt->callid_name);
+                               }
+                               if (!strcasecmp(prop, "CONF_ID") && !strcasecmp(value, "0")) {
+                                       //DEBUGA_SKYPE("the skype_call %s is NOT a conference call\n", SKYPIAX_P_LOG, id);
+                                       //if (tech_pvt->interface_state == SKYPIAX_STATE_DOWN)
+                                       //tech_pvt->interface_state = SKYPIAX_STATE_PRERING;
+                               }
+                               if (!strcasecmp(prop, "CONF_ID") && strcasecmp(value, "0")) {
+                                       DEBUGA_SKYPE("the skype_call %s is a conference call\n", SKYPIAX_P_LOG, id);
+                                       //if (tech_pvt->interface_state == SKYPIAX_STATE_DOWN)
+                                       //tech_pvt->interface_state = SKYPIAX_STATE_PRERING;
+                               }
+                               if (!strcasecmp(prop, "DTMF")) {
+                                       DEBUGA_SKYPE("Call %s received a DTMF: %s\n", SKYPIAX_P_LOG, id, value);
+                                       dtmf_received(tech_pvt, value);
+                               }
+                               if (!strcasecmp(prop, "FAILUREREASON")) {
+                                       DEBUGA_SKYPE("Skype FAILED on skype_call %s. Let's wait for the FAILED message.\n", SKYPIAX_P_LOG, id);
+                               }
+                               if (!strcasecmp(prop, "DURATION") && (!strcasecmp(value, "1"))) {
+                                       if (strcasecmp(id, tech_pvt->skype_call_id)) {
+                                               skypiax_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
+                                               DEBUGA_SKYPE("We called a Skype contact and he answered us on skype_call: %s.\n", SKYPIAX_P_LOG, id);
+                                       }
+                               }
+
+                               if (!strcasecmp(prop, "DURATION") && (tech_pvt->interface_state == SKYPIAX_STATE_ERROR_DOUBLE_CALL)) {
+                                       char msg_to_skype[1024];
+                                       skypiax_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
+                                       ERRORA("We are in a double call situation, trying to get out hanging up call id: %s.\n", SKYPIAX_P_LOG, id);
+                                       sprintf(msg_to_skype, "ALTER CALL %s HANGUP", id);
+                                       skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                       skypiax_sleep(10000);
+                                       //return CALLFLOW_INCOMING_HANGUP;
+                               }
+
+                               if (!strcasecmp(prop, "STATUS")) {
+
+                                       if (!strcasecmp(value, "RINGING")) {
+                                               char msg_to_skype[1024];
+                                               if ((tech_pvt->interface_state != SKYPIAX_STATE_SELECTED && tech_pvt->interface_state != SKYPIAX_STATE_DIALING)
+                                                       && (!strlen(tech_pvt->skype_call_id) || !strlen(tech_pvt->session_uuid_str))) {
+                                                       /* we are NOT inside an active call */
+
+                                                       DEBUGA_SKYPE("NO ACTIVE calls in this moment, skype_call %s is RINGING, to ask PARTNER_HANDLE\n", SKYPIAX_P_LOG, id);
+                                                       sprintf(msg_to_skype, "GET CALL %s PARTNER_HANDLE", id);
+                                                       skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                                       skypiax_sleep(10000);
+                                               } else {
+                                                       /* we are inside an active call */
+                                                       if (!strcasecmp(tech_pvt->skype_call_id, id)) {
+                                                               /* this is the call in which we are calling out */
+                                                               tech_pvt->skype_callflow = CALLFLOW_STATUS_RINGING;
+                                                               tech_pvt->interface_state = SKYPIAX_STATE_RINGING;
+                                                               skypiax_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
+                                                               DEBUGA_SKYPE("Our remote party in skype_call %s is RINGING\n", SKYPIAX_P_LOG, id);
+                                                               remote_party_is_ringing(tech_pvt);
+                                                       } else {
+                                                               DEBUGA_SKYPE
+                                                                       ("We are in another call, but skype_call %s is RINGING on us, let's ask PARTNER_HANDLE, so maybe we'll TRANSFER\n",
+                                                                        SKYPIAX_P_LOG, id);
+                                                               sprintf(msg_to_skype, "GET CALL %s PARTNER_HANDLE", id);
+                                                               skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                                               skypiax_sleep(10000);
+                                                       }
+                                               }
+                                       } else if (!strcasecmp(value, "EARLYMEDIA")) {
+                                               char msg_to_skype[1024];
+                                               tech_pvt->skype_callflow = CALLFLOW_STATUS_EARLYMEDIA;
+                                               tech_pvt->interface_state = SKYPIAX_STATE_DIALING;
+                                               DEBUGA_SKYPE("Our remote party in skype_call %s is EARLYMEDIA\n", SKYPIAX_P_LOG, id);
+                                               if (tech_pvt->tcp_cli_thread == NULL) {
+                                                       DEBUGA_SKYPE("START start_audio_threads\n", SKYPIAX_P_LOG);
+                                                       if (start_audio_threads(tech_pvt)) {
+                                                               ERRORA("start_audio_threads FAILED\n", SKYPIAX_P_LOG);
+                                                               return CALLFLOW_INCOMING_HANGUP;
+                                                       }
+                                               }
+                                               skypiax_sleep(1000);
+                                               sprintf(msg_to_skype, "ALTER CALL %s SET_INPUT PORT=\"%d\"", id, tech_pvt->tcp_cli_port);
+                                               skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                               sprintf(msg_to_skype, "#output ALTER CALL %s SET_OUTPUT PORT=\"%d\"", id, tech_pvt->tcp_srv_port);
+                                               skypiax_signaling_write(tech_pvt, msg_to_skype);
+
+                                               remote_party_is_early_media(tech_pvt);
+                                       } else if (!strcasecmp(value, "MISSED")) {
+                                               DEBUGA_SKYPE("We missed skype_call %s\n", SKYPIAX_P_LOG, id);
+                                       } else if (!strcasecmp(value, "FINISHED")) {
+                                               //DEBUGA_SKYPE("skype_call %s now is DOWN\n", SKYPIAX_P_LOG, id);
+                                               if (!strcasecmp(tech_pvt->skype_call_id, id)) {
+                                                       //tech_pvt->skype_callflow = CALLFLOW_STATUS_FINISHED;
+                                                       DEBUGA_SKYPE("skype_call %s is MY call, now I'm going DOWN\n", SKYPIAX_P_LOG, id);
+                                                       //tech_pvt->skype_call_id[0] = '\0';
+                                                       if (tech_pvt->interface_state != SKYPIAX_STATE_HANGUP_REQUESTED) {
+                                                               //tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                                               return CALLFLOW_INCOMING_HANGUP;
+                                                       } else {
+                                                               tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                                       }
+                                               } else {
+                                                       DEBUGA_SKYPE("skype_call %s is NOT MY call, ignoring\n", SKYPIAX_P_LOG, id);
+                                               }
+
+                                       } else if (!strcasecmp(value, "CANCELLED")) {
+                                               tech_pvt->skype_callflow = CALLFLOW_STATUS_CANCELLED;
+                                               DEBUGA_SKYPE("we tried to call Skype on skype_call %s and Skype has now CANCELLED\n", SKYPIAX_P_LOG, id);
+                                               tech_pvt->skype_call_id[0] = '\0';
+                                               if (tech_pvt->interface_state != SKYPIAX_STATE_HANGUP_REQUESTED) {
+                                                       tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                                       return CALLFLOW_INCOMING_HANGUP;
+                                               } else {
+                                                       tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                               }
+                                       } else if (!strcasecmp(value, "FAILED")) {
+                                               tech_pvt->skype_callflow = CALLFLOW_STATUS_FAILED;
+                                               DEBUGA_SKYPE("we tried to call Skype on skype_call %s and Skype has now FAILED\n", SKYPIAX_P_LOG, id);
+                                               tech_pvt->skype_call_id[0] = '\0';
+                                               skypiax_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
+                                               tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                               return CALLFLOW_INCOMING_HANGUP;
+                                       } else if (!strcasecmp(value, "REFUSED")) {
+                                               if (!strcasecmp(id, tech_pvt->skype_call_id)) {
+                                                       /* this is the id of the call we are in, probably we generated it */
+                                                       tech_pvt->skype_callflow = CALLFLOW_STATUS_REFUSED;
+                                                       DEBUGA_SKYPE("we tried to call Skype on skype_call %s and Skype has now REFUSED\n", SKYPIAX_P_LOG, id);
+                                                       skypiax_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
+                                                       tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                                       tech_pvt->skype_call_id[0] = '\0';
+                                                       return CALLFLOW_INCOMING_HANGUP;
+                                               } else {
+                                                       /* we're here because were us that refused an incoming call */
+                                                       DEBUGA_SKYPE("we REFUSED skype_call %s\n", SKYPIAX_P_LOG, id);
+                                               }
+                                       } else if (!strcasecmp(value, "TRANSFERRING")) {
+                                               DEBUGA_SKYPE("skype_call %s is transferring\n", SKYPIAX_P_LOG, id);
+                                       } else if (!strcasecmp(value, "TRANSFERRED")) {
+                                               DEBUGA_SKYPE("skype_call %s has been transferred\n", SKYPIAX_P_LOG, id);
+                                       } else if (!strcasecmp(value, "ROUTING")) {
+                                               tech_pvt->skype_callflow = CALLFLOW_STATUS_ROUTING;
+                                               tech_pvt->interface_state = SKYPIAX_STATE_DIALING;
+                                               skypiax_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
+                                               DEBUGA_SKYPE("skype_call: %s is now ROUTING\n", SKYPIAX_P_LOG, id);
+                                       } else if (!strcasecmp(value, "UNPLACED")) {
+                                               tech_pvt->skype_callflow = CALLFLOW_STATUS_UNPLACED;
+                                               tech_pvt->interface_state = SKYPIAX_STATE_DIALING;
+                                               skypiax_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
+                                               DEBUGA_SKYPE("skype_call: %s is now UNPLACED\n", SKYPIAX_P_LOG, id);
+                                       } else if (!strcasecmp(value, "INPROGRESS")) {
+                                               char msg_to_skype[1024];
+
+                                               if (!strlen(tech_pvt->session_uuid_str)) {
+                                                       DEBUGA_SKYPE("no tech_pvt->session_uuid_str\n", SKYPIAX_P_LOG);
+                                               }
+                                               if (tech_pvt->skype_callflow != CALLFLOW_STATUS_REMOTEHOLD) {
+                                                       if (!strlen(tech_pvt->session_uuid_str) || !strlen(tech_pvt->skype_call_id)
+                                                               || !strcasecmp(tech_pvt->skype_call_id, id)) {
+                                                               skypiax_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
+                                                               DEBUGA_SKYPE("skype_call: %s is now active\n", SKYPIAX_P_LOG, id);
+
+                                                               if (tech_pvt->skype_callflow != CALLFLOW_STATUS_EARLYMEDIA) {
+                                                                       tech_pvt->skype_callflow = CALLFLOW_STATUS_INPROGRESS;
+                                                                       tech_pvt->interface_state = SKYPIAX_STATE_UP;
+
+                                                                       if (tech_pvt->tcp_cli_thread == NULL) {
+                                                                               DEBUGA_SKYPE("START start_audio_threads\n", SKYPIAX_P_LOG);
+                                                                               if (start_audio_threads(tech_pvt)) {
+                                                                                       ERRORA("start_audio_threads FAILED\n", SKYPIAX_P_LOG);
+                                                                                       return CALLFLOW_INCOMING_HANGUP;
+                                                                               }
+                                                                       }
+                                                                       skypiax_sleep(1000);    //FIXME
+                                                                       sprintf(msg_to_skype, "ALTER CALL %s SET_INPUT PORT=\"%d\"", id, tech_pvt->tcp_cli_port);
+                                                                       skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                                                       skypiax_sleep(1000);    //FIXME
+                                                                       sprintf(msg_to_skype, "#output ALTER CALL %s SET_OUTPUT PORT=\"%d\"", id, tech_pvt->tcp_srv_port);
+                                                                       skypiax_signaling_write(tech_pvt, msg_to_skype);
+                                                               }
+                                                               tech_pvt->skype_callflow = CALLFLOW_STATUS_INPROGRESS;
+                                                               if (!strlen(tech_pvt->session_uuid_str)) {
+                                                                       DEBUGA_SKYPE("New Inbound Channel!\n\n\n\n", SKYPIAX_P_LOG);
+                                                                       new_inbound_channel(tech_pvt);
+                                                               } else {
+                                                                       tech_pvt->interface_state = SKYPIAX_STATE_UP;
+                                                                       DEBUGA_SKYPE("Outbound Channel Answered! session_uuid_str=%s\n", SKYPIAX_P_LOG, tech_pvt->session_uuid_str);
+                                                                       outbound_channel_answered(tech_pvt);
+                                                               }
+                                                       } else {
+                                                               DEBUGA_SKYPE("I'm on %s, skype_call %s is NOT MY call, ignoring\n", SKYPIAX_P_LOG, tech_pvt->skype_call_id, id);
+                                                       }
+                                               } else {
+                                                       tech_pvt->skype_callflow = CALLFLOW_STATUS_INPROGRESS;
+                                                       DEBUGA_SKYPE("Back from REMOTEHOLD!\n", SKYPIAX_P_LOG);
+                                               }
+
+                                       } else if (!strcasecmp(value, "REMOTEHOLD")) {
+                                               tech_pvt->skype_callflow = CALLFLOW_STATUS_REMOTEHOLD;
+                                               DEBUGA_SKYPE("skype_call: %s is now REMOTEHOLD\n", SKYPIAX_P_LOG, id);
+
+                                       } else if (!strcasecmp(value, "BUSY")) {
+                                               tech_pvt->skype_callflow = CALLFLOW_STATUS_FAILED;
+                                               DEBUGA_SKYPE
+                                                       ("we tried to call Skype on skype_call %s and remote party (destination) was BUSY. Our outbound call has failed\n",
+                                                        SKYPIAX_P_LOG, id);
+                                               skypiax_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
+                                               tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                               tech_pvt->skype_call_id[0] = '\0';
+                                               skypiax_sleep(1000);
+                                               return CALLFLOW_INCOMING_HANGUP;
+                                       } else if (!strcasecmp(value, "WAITING_REDIAL_COMMAND")) {
+                                               tech_pvt->skype_callflow = CALLFLOW_STATUS_FAILED;
+                                               DEBUGA_SKYPE
+                                                       ("we tried to call Skype on skype_call %s and remote party (destination) has rejected us (WAITING_REDIAL_COMMAND). Our outbound call has failed\n",
+                                                        SKYPIAX_P_LOG, id);
+                                               skypiax_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1);
+                                               tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                                               tech_pvt->skype_call_id[0] = '\0';
+                                               skypiax_sleep(1000);
+                                               return CALLFLOW_INCOMING_HANGUP;
+                                       } else {
+                                               WARNINGA("skype_call: %s, STATUS: %s is not recognized\n", SKYPIAX_P_LOG, id, value);
+                                       }
+                               }                               //STATUS
+                       }                                       //CALL
+                       /* the "numbered" messages that follows are used by the directory application, not yet ported */
+                       if (!strcasecmp(message, "#333")) {
+                               /* DEBUGA_SKYPE("Skype MSG: message_2: %s, message2[11]: %s\n", SKYPIAX_P_LOG,
+                                * message_2, &message_2[11]); */
+                               memset(tech_pvt->skype_friends, 0, 4096);
+                               skypiax_strncpy(tech_pvt->skype_friends, &message_2[11], 4095);
+                       }
+                       if (!strcasecmp(message, "#222")) {
+                               /* DEBUGA_SKYPE("Skype MSG: message_2: %s, message2[10]: %s\n", SKYPIAX_P_LOG,
+                                * message_2, &message_2[10]); */
+                               memset(tech_pvt->skype_fullname, 0, 512);
+                               skypiax_strncpy(tech_pvt->skype_fullname, &message_2[10], 511);
+                       }
+                       if (!strcasecmp(message, "#765")) {
+                               /* DEBUGA_SKYPE("Skype MSG: message_2: %s, message2[10]: %s\n", SKYPIAX_P_LOG,
+                                * message_2, &message_2[10]); */
+                               memset(tech_pvt->skype_displayname, 0, 512);
+                               skypiax_strncpy(tech_pvt->skype_displayname, &message_2[10], 511);
+                       }
+                       a = 0;
+               }                                               //message end
+       }                                                       //read_from_pipe
+       return 0;
+}
+
+void *skypiax_do_tcp_srv_thread_func(void *obj)
+{
+       private_t *tech_pvt = obj;
+       int s;
+       unsigned int len;
+       unsigned int i;
+       unsigned int a;
+#if defined(WIN32) && !defined(__CYGWIN__)
+       int sin_size;
+#else /* WIN32 */
+       unsigned int sin_size;
+#endif /* WIN32 */
+       unsigned int fd;
+       short srv_in[SAMPLES_PER_FRAME];
+       short srv_out[SAMPLES_PER_FRAME / 2];
+       //struct sockaddr_in my_addr;
+       struct sockaddr_in remote_addr;
+       //int exit = 0;
+       unsigned int kill_cli_size;
+       short kill_cli_buff[SAMPLES_PER_FRAME];
+       short totalbuf[SAMPLES_PER_FRAME];
+       int sockbufsize = 0;
+       unsigned int size = sizeof(int);
+
+       s = skypiax_socket_create_and_bind(tech_pvt, &tech_pvt->tcp_srv_port);
+       if (s < 0) {
+               ERRORA("skypiax_socket_create_and_bind error!\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 (tech_pvt->interface_state != SKYPIAX_STATE_DOWN
+                  && (tech_pvt->skype_callflow == CALLFLOW_STATUS_INPROGRESS
+                          || tech_pvt->skype_callflow == CALLFLOW_STATUS_EARLYMEDIA
+                          || tech_pvt->skype_callflow == CALLFLOW_STATUS_REMOTEHOLD || tech_pvt->skype_callflow == SKYPIAX_STATE_UP)) {
+
+               unsigned int fdselectgio;
+               int rtgio;
+               fd_set fsgio;
+               struct timeval togio;
+
+               if (!(running && tech_pvt->running))
+                       break;
+               FD_ZERO(&fsgio);
+               togio.tv_usec = 20000;  //20msec
+               togio.tv_sec = 0;
+               fdselectgio = s;
+               FD_SET(fdselectgio, &fsgio);
+
+               rtgio = select(fdselectgio + 1, &fsgio, NULL, NULL, &togio);
+
+               if (rtgio) {
+
+  /****************************/
+
+                       while (s > 0 && (fd = accept(s, (struct sockaddr *) &remote_addr, &sin_size)) > 0) {
+                               DEBUGA_SKYPE("ACCEPTED here I send you %d\n", SKYPIAX_P_LOG, tech_pvt->tcp_srv_port);
+
+                               sockbufsize = 0;
+                               size = sizeof(int);
+                               getsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *) &sockbufsize, &size);
+                               DEBUGA_SKYPE("3 SO_RCVBUF is %d, size is %d\n", SKYPIAX_P_LOG, sockbufsize, size);
+                               sockbufsize = 0;
+                               size = sizeof(int);
+                               getsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *) &sockbufsize, &size);
+                               DEBUGA_SKYPE("3 SO_SNDBUF is %d, size is %d\n", SKYPIAX_P_LOG, sockbufsize, size);
+
+
+                               if (!(running && tech_pvt->running))
+                                       break;
+                               while (tech_pvt->interface_state != SKYPIAX_STATE_DOWN
+                                          && (tech_pvt->skype_callflow == CALLFLOW_STATUS_INPROGRESS
+                                                  || tech_pvt->skype_callflow == CALLFLOW_STATUS_EARLYMEDIA
+                                                  || tech_pvt->skype_callflow == CALLFLOW_STATUS_REMOTEHOLD || tech_pvt->skype_callflow == SKYPIAX_STATE_UP)) {
+
+                                       unsigned int fdselect;
+                                       int rt;
+                                       fd_set fs;
+                                       struct timeval to;
+
+                                       if (!(running && tech_pvt->running))
+                                               break;
+                                       //exit = 1;
+
+                                       fdselect = fd;
+                                       FD_ZERO(&fs);
+                                       FD_SET(fdselect, &fs);
+                                       //to.tv_usec = 2000000;     //2000 msec
+                                       to.tv_usec = 60000;     //60 msec
+                                       to.tv_sec = 0;
+
+                                        if (tech_pvt->timer_read.timer_interface && tech_pvt->timer_read.timer_interface->timer_next) {
+       switch_core_timer_next(&tech_pvt->timer_read);
+                                        }
+                                       rt = select(fdselect + 1, &fs, NULL, NULL, &to);
+                                       if (rt > 0) {
+
+                                               if (tech_pvt->skype_callflow != CALLFLOW_STATUS_REMOTEHOLD) {
+                                                       len = recv(fd, (char *) srv_in, 640, 0);        //seems that Skype only sends 320 bytes at time
+                                               } else {
+                                                       len = 0;
+                                               }
+
+                                               if (len == 320) {
+                                                       unsigned int howmany;
+
+                                                               ERRORA("320!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n", SKYPIAX_P_LOG);
+                                                       if (samplerate_skypiax == 8000) {
+                                                               /* we're downsampling from 16khz to 8khz, srv_out will contain each other sample from srv_in */
+                                                               a = 0;
+                                                               for (i = 0; i < len / sizeof(short); i++) {
+                                                                       srv_out[a] = srv_in[i];
+                                                                       i++;
+                                                                       a++;
+                                                               }
+                                                       } else if (samplerate_skypiax == 16000) {
+                                                               /* we're NOT downsampling, srv_out will contain ALL samples from srv_in */
+                                                               for (i = 0; i < len / sizeof(short); i++) {
+                                                                       srv_out[i] = srv_in[i];
+                                                               }
+                                                       } else {
+                                                               ERRORA("SAMPLERATE_SKYPIAX can only be 8000 or 16000\n", SKYPIAX_P_LOG);
+                                                       }
+                                                       /* if not yet done, let's store the half incoming frame */
+                                                       if (!tech_pvt->audiobuf_is_loaded) {
+                                                               for (i = 0; i < SAMPLES_PER_FRAME / 2; i++) {
+                                                                       tech_pvt->audiobuf[i] = srv_out[i];
+                                                               }
+                                                               tech_pvt->audiobuf_is_loaded = 1;
+                                                       } else {
+                                                               /* we got a stored half frame, build a complete frame in totalbuf using the stored half frame and the current half frame */
+                                                               for (i = 0; i < SAMPLES_PER_FRAME / 2; i++) {
+                                                                       totalbuf[i] = tech_pvt->audiobuf[i];
+                                                               }
+                                                               for (a = 0; a < SAMPLES_PER_FRAME / 2; a++) {
+                                                                       totalbuf[i] = srv_out[a];
+                                                                       i++;
+                                                               }
+                                                               /* send the complete frame through the pipe to our code waiting for incoming audio */
+                                                               //howmany = skypiax_pipe_write(tech_pvt->audiopipe_srv[1], totalbuf, SAMPLES_PER_FRAME * sizeof(short));
+                                                               //FIXME while(tech_pvt->flag_audio_srv == 1){
+                                                               //FIXME switch_sleep(100); //1 millisec
+                                                               //NOTICA("read now is 1\n", SKYPIAX_P_LOG);
+                                                               //FIXME }
+                                                               //WARNINGA("read is now 0\n", SKYPIAX_P_LOG);
+
+
+                                                               howmany = SAMPLES_PER_FRAME * sizeof(short);
+                                                               if (tech_pvt->flag_audio_srv == 1) {
+                                                                       switch_sleep(1000);     //1 millisec
+                                                               }
+                                                               //if (tech_pvt->flag_audio_srv == 0) {
+                       switch_mutex_lock(tech_pvt->mutex_audio_srv);
+                                                                       memcpy(tech_pvt->audiobuf_srv, totalbuf, SAMPLES_PER_FRAME * sizeof(short));
+                                                                       tech_pvt->flag_audio_srv = 1;
+                       switch_mutex_unlock(tech_pvt->mutex_audio_srv);
+                                                               //}
+                                                               //NOTICA("read \n", SKYPIAX_P_LOG);
+                                                               if (howmany != SAMPLES_PER_FRAME * sizeof(short)) {
+                                                                       ERRORA("howmany is %d, but was expected to be %d\n", SKYPIAX_P_LOG,
+                                                                                  howmany, (int) (SAMPLES_PER_FRAME * sizeof(short)));
+                                                               }
+                                                               /* done with the stored half frame */
+                                                               tech_pvt->audiobuf_is_loaded = 0;
+                                                       }
+
+                                               } else if (len == 640) {
+
+                                                               if (tech_pvt->flag_audio_srv == 1) {
+                                                                       switch_sleep(1000);     //1 millisec
+                                                               }
+                       switch_mutex_lock(tech_pvt->mutex_audio_srv);
+                                                                       memcpy(tech_pvt->audiobuf_srv, srv_in, SAMPLES_PER_FRAME * sizeof(short));
+                                                                       tech_pvt->flag_audio_srv = 1;
+                       switch_mutex_unlock(tech_pvt->mutex_audio_srv);
+                                               } else if (len == 0) {
+                                                       skypiax_sleep(1000);
+                                               } else {
+                                                       ERRORA("len=%d, expected 640\n", SKYPIAX_P_LOG, len);
+                                               }
+
+                                       } else {
+                                               if (rt)
+                                                       ERRORA("SRV rt=%d\n", SKYPIAX_P_LOG, rt);
+                                               skypiax_sleep(10000);
+                                       }
+
+                               }
+
+                               /* let's send some frame in the pipes, so both tcp_cli and tcp_srv will have an occasion to die */
+                               kill_cli_size = SAMPLES_PER_FRAME * sizeof(short);
+                               len = skypiax_pipe_write(tech_pvt->audiopipe_srv[1], kill_cli_buff, kill_cli_size);
+                               kill_cli_size = SAMPLES_PER_FRAME * sizeof(short);
+                               len = skypiax_pipe_write(tech_pvt->audiopipe_cli[1], kill_cli_buff, kill_cli_size);
+                               //tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                               kill_cli_size = SAMPLES_PER_FRAME * sizeof(short);
+                               len = skypiax_pipe_write(tech_pvt->audiopipe_srv[1], kill_cli_buff, kill_cli_size);
+                               kill_cli_size = SAMPLES_PER_FRAME * sizeof(short);
+                               len = skypiax_pipe_write(tech_pvt->audiopipe_cli[1], kill_cli_buff, kill_cli_size);
+
+                               tech_pvt->flag_audio_cli = 1;   //let's send some frame in the pipes, so both tcp_cli and tcp_srv will have an occasion to die
+                               skypiax_sleep(2000);
+                               tech_pvt->flag_audio_srv = 1;   //let's send some frame in the pipes, so both tcp_cli and tcp_srv will have an occasion to die
+                               skypiax_sleep(2000);
+                               tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
+                               tech_pvt->flag_audio_cli = 1;   //let's send some frame in the pipes, so both tcp_cli and tcp_srv will have an occasion to die
+                               skypiax_sleep(2000);
+                               tech_pvt->flag_audio_srv = 1;   //let's send some frame in the pipes, so both tcp_cli and tcp_srv will have an occasion to die
+                               skypiax_sleep(2000);
+                               DEBUGA_SKYPE("Skype incoming audio GONE\n", SKYPIAX_P_LOG);
+                               skypiax_close_socket(fd);
+                       }
+               }
+       }
+
+       DEBUGA_SKYPE("incoming audio server (I am it) EXITING\n", SKYPIAX_P_LOG);
+       skypiax_close_socket(s);
+       s = -1;
+       return NULL;
+}
+
+void *skypiax_do_tcp_cli_thread_func(void *obj)
+{
+       private_t *tech_pvt = obj;
+       int s;
+       //struct sockaddr_in my_addr;
+       struct sockaddr_in remote_addr;
+       unsigned int got;
+       unsigned int len;
+       unsigned int i;
+       unsigned int a;
+       unsigned int fd;
+       short cli_out[SAMPLES_PER_FRAME * 2];
+       short cli_in[SAMPLES_PER_FRAME];
+#ifdef WIN32
+       int sin_size;
+#else
+       unsigned int sin_size;
+#endif /* WIN32 */
+       int sockbufsize = 0;
+       unsigned int size = sizeof(int);
+
+       s = skypiax_socket_create_and_bind(tech_pvt, &tech_pvt->tcp_cli_port);
+       if (s < 0) {
+               ERRORA("skypiax_socket_create_and_bind error!\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 (tech_pvt->interface_state != SKYPIAX_STATE_DOWN
+                  && (tech_pvt->skype_callflow == CALLFLOW_STATUS_INPROGRESS
+                          || tech_pvt->skype_callflow == CALLFLOW_STATUS_EARLYMEDIA
+                          || tech_pvt->skype_callflow == CALLFLOW_STATUS_REMOTEHOLD || tech_pvt->skype_callflow == SKYPIAX_STATE_UP)) {
+
+               unsigned int fdselectgio;
+               int rtgio;
+               fd_set fsgio;
+               struct timeval togio;
+
+               if (!(running && tech_pvt->running))
+                       break;
+               FD_ZERO(&fsgio);
+               togio.tv_usec = 20000;  //20msec
+               togio.tv_sec = 0;
+               fdselectgio = s;
+               FD_SET(fdselectgio, &fsgio);
+
+               rtgio = select(fdselectgio + 1, &fsgio, NULL, NULL, &togio);
+
+               if (rtgio) {
+
+  /****************************/
+
+                       while (s > 0 && (fd = accept(s, (struct sockaddr *) &remote_addr, &sin_size)) > 0) {
+                               DEBUGA_SKYPE("ACCEPTED here you send me %d\n", SKYPIAX_P_LOG, tech_pvt->tcp_cli_port);
+
+                               sockbufsize = 0;
+                               size = sizeof(int);
+                               getsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *) &sockbufsize, &size);
+                               DEBUGA_SKYPE("4 SO_RCVBUF is %d, size is %d\n", SKYPIAX_P_LOG, sockbufsize, size);
+                               sockbufsize = 0;
+                               size = sizeof(int);
+                               getsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *) &sockbufsize, &size);
+                               DEBUGA_SKYPE("4 SO_SNDBUF is %d, size is %d\n", SKYPIAX_P_LOG, sockbufsize, size);
+
+
+
+#ifndef WIN32
+                               fcntl(tech_pvt->audiopipe_cli[0], F_SETFL, O_NONBLOCK);
+                               fcntl(tech_pvt->audiopipe_cli[1], F_SETFL, O_NONBLOCK);
+#endif //WIN32
+
+                               if (!(running && tech_pvt->running))
+                                       break;
+                               while (tech_pvt->interface_state != SKYPIAX_STATE_DOWN
+                                          && (tech_pvt->skype_callflow == CALLFLOW_STATUS_INPROGRESS
+                                                  || tech_pvt->skype_callflow == CALLFLOW_STATUS_EARLYMEDIA
+                                                  || tech_pvt->skype_callflow == CALLFLOW_STATUS_REMOTEHOLD || tech_pvt->skype_callflow == SKYPIAX_STATE_UP)) {
+                                       unsigned int fdselect;
+                                       int rt;
+                                       fd_set fs;
+                                       struct timeval to;
+                                       int waitin;
+                                       int big_waitin=40;
+                                       int lil_waitin=20;
+                                       int big_waited;
+
+                                       if (!(running && tech_pvt->running))
+                                               break;
+                                       FD_ZERO(&fs);
+                                       to.tv_usec = 120000;    //120msec
+                                       to.tv_sec = 0;
+#if defined(WIN32) && !defined(__CYGWIN__)
+/* on win32 we cannot select from the apr "pipe", so we select on socket writability */
+                                       fdselect = fd;
+                                       FD_SET(fdselect, &fs);
+
+                                       //rt = select(fdselect + 1, NULL, &fs, NULL, &to);
+#else
+/* on *unix and cygwin we select from the real pipe */
+                                       //XXX fdselect = tech_pvt->audiopipe_cli[0];
+                                       //XXX FD_SET(fdselect, &fs);
+
+                                       //rt = select(fdselect + 1, &fs, NULL, NULL, &to);
+#endif
+                                       fdselect = fd;
+                                       FD_SET(fdselect, &fs);
+
+                                       //FIXME rt = select(fdselect + 1, NULL, &fs, NULL, &to);
+                                       waitin=0;
+                                       big_waited=0;
+                                       while (tech_pvt->flag_audio_cli == 0) {
+#ifdef WIN32
+                                               skypiax_sleep(100);     //0.1 millisec
+#else
+                                               skypiax_sleep(1000);    //1 millisec
+#endif //WIN32
+                                               waitin++;
+                                               if(big_waited == 1 && waitin==lil_waitin && tech_pvt->flag_audio_cli == 0){
+                                                       memset(cli_out, 255, SAMPLES_PER_FRAME * sizeof(short));
+                                                       send(fd, (char *) cli_out, SAMPLES_PER_FRAME * sizeof(short), 0);
+                                                       //WARNINGA("write buffer filled at %d\n", SKYPIAX_P_LOG, waitin);
+                                                       waitin=0;
+                                                       continue;
+                                               }
+                                               if(big_waited == 0 && waitin==big_waitin && tech_pvt->flag_audio_cli == 0){
+                                                       memset(cli_out, 255, SAMPLES_PER_FRAME * sizeof(short));
+                                                       send(fd, (char *) cli_out, SAMPLES_PER_FRAME * sizeof(short), 0);
+                                                       send(fd, (char *) cli_out, SAMPLES_PER_FRAME * sizeof(short), 0);
+                                                       WARNINGA("write buffer filled at %d\n", SKYPIAX_P_LOG, waitin);
+                                                       waitin=0;
+                                                       big_waited=1;
+                                                       continue;
+                                               }
+
+                                       }
+                                       if(waitin > 21)
+                                               ERRORA("waitin is now %d\n", SKYPIAX_P_LOG, waitin);
+                                       if(!waitin)
+                                       NOTICA("waitin is now %d\n", SKYPIAX_P_LOG, waitin);
+
+                                       rt = 1;
+
+                                       if (rt > 0) {
+                                               int counter;
+
+                                               /* until we drained the pipe to empty */
+                                               //for (counter = 0; counter < 10; counter++) {
+                                               for (counter = 0; counter < 1; counter++) {
+                                                       /* read from the pipe the audio frame we are supposed to send out */
+                                                       //got = skypiax_pipe_read(tech_pvt->audiopipe_cli[0], cli_in, SAMPLES_PER_FRAME * sizeof(short));
+
+
+                                                       got = SAMPLES_PER_FRAME * sizeof(short);
+                                                       memcpy(cli_in, tech_pvt->audiobuf_cli, SAMPLES_PER_FRAME * sizeof(short));
+                                                       tech_pvt->flag_audio_cli = 0;
+
+
+
+
+                                                       if (got == -1)
+                                                               break;
+
+                                                       if (got != SAMPLES_PER_FRAME * sizeof(short)) {
+                                                               WARNINGA("got is %d, but was expected to be %d\n", SKYPIAX_P_LOG, got, (int) (SAMPLES_PER_FRAME * sizeof(short)));
+                                                       }
+
+                                                       if (got == SAMPLES_PER_FRAME * sizeof(short)) {
+                                                               if (samplerate_skypiax == 8000) {
+
+                                                                       /* we're upsampling from 8khz to 16khz, cli_out will contain two times each sample from cli_in */
+                                                                       a = 0;
+                                                                       for (i = 0; i < got / sizeof(short); i++) {
+                                                                               cli_out[a] = cli_in[i];
+                                                                               a++;
+                                                                               cli_out[a] = cli_in[i];
+                                                                               a++;
+                                                                       }
+                                                                       got = got * 2;
+                                                               } else if (samplerate_skypiax == 16000) {
+                                                                       /* we're NOT upsampling, cli_out will contain just ALL samples from cli_in */
+                                                                       for (i = 0; i < got / sizeof(short); i++) {
+                                                                               cli_out[i] = cli_in[i];
+                                                                       }
+                                                               } else {
+                                                                       ERRORA("SAMPLERATE_SKYPIAX can only be 8000 or 16000\n", SKYPIAX_P_LOG);
+                                                               }
+
+                                                               /* send the 16khz frame to the Skype client waiting for incoming audio to be sent to the remote party */
+                                                               if (tech_pvt->skype_callflow != CALLFLOW_STATUS_REMOTEHOLD) {
+                                                                       len = send(fd, (char *) cli_out, got, 0);
+                                                                       //skypiax_sleep(5000);  //5 msec
+
+                                                                       if (len == -1) {
+                                                                               break;
+                                                                       } else if (len != got) {
+                                                                               ERRORA("len=%d\n", SKYPIAX_P_LOG, len);
+                                                                               skypiax_sleep(1000);
+                                                                               break;
+                                                                       }
+                                                               }
+
+                                                       } else {
+
+                                                               WARNINGA("got is %d, but was expected to be %d\n", SKYPIAX_P_LOG, got, (int) (SAMPLES_PER_FRAME * sizeof(short)));
+                                                       }
+                                               }
+                                       } else {
+                                               if (rt)
+                                                       ERRORA("CLI rt=%d\n", SKYPIAX_P_LOG, rt);
+                                               memset(cli_out, 0, sizeof(cli_out));
+                                               if (tech_pvt->skype_callflow != CALLFLOW_STATUS_REMOTEHOLD) {
+                                                       len = send(fd, (char *) cli_out, sizeof(cli_out), 0);
+                                                       len = send(fd, (char *) cli_out, sizeof(cli_out) / 2, 0);
+                                                       //WARNINGA("sent %d of zeros to keep the Skype client socket busy\n", SKYPIAX_P_LOG, sizeof(cli_out) + sizeof(cli_out)/2);
+                                               } else {
+                                                       /*
+                                                          XXX do nothing 
+                                                        */
+                                                       //WARNINGA("we don't send it\n", SKYPIAX_P_LOG);
+                                               }
+                                               skypiax_sleep(1000);
+                                       }
+
+                               }
+                               DEBUGA_SKYPE("Skype outbound audio GONE\n", SKYPIAX_P_LOG);
+                               skypiax_close_socket(fd);
+                       }
+               }
+       }
+
+       DEBUGA_SKYPE("outbound audio server (I am it) EXITING\n", SKYPIAX_P_LOG);
+       skypiax_close_socket(s);
+       s = -1;
+       return NULL;
+}
+
+int skypiax_audio_read(private_t * tech_pvt)
+{
+       unsigned int samples;
+       int waitin;
+
+       waitin=0;
+       while (tech_pvt->flag_audio_srv == 0) {
+#ifdef WIN32
+               skypiax_sleep(100);             //0.1 millisec
+#else
+               skypiax_sleep(1000);    //1 millisec
+#endif //WIN32
+               waitin++;
+
+               //WARNINGA("read now is 0\n", SKYPIAX_P_LOG);
+       }
+       if(waitin > 21)
+       NOTICA("read is now %d\n", SKYPIAX_P_LOG, waitin);
+       //samples = skypiax_pipe_read(tech_pvt->audiopipe_srv[0], tech_pvt->read_frame.data, SAMPLES_PER_FRAME * sizeof(short));
+                       switch_mutex_lock(tech_pvt->mutex_audio_srv);
+       memcpy(tech_pvt->read_frame.data, tech_pvt->audiobuf_srv, SAMPLES_PER_FRAME * sizeof(short));
+       tech_pvt->flag_audio_srv = 0;
+                       switch_mutex_unlock(tech_pvt->mutex_audio_srv);
+
+       samples = SAMPLES_PER_FRAME * sizeof(short);
+       if (samples != SAMPLES_PER_FRAME * sizeof(short)) {
+               if (samples)
+                       WARNINGA("read samples=%u expected=%u\n", SKYPIAX_P_LOG, samples, (int) (SAMPLES_PER_FRAME * sizeof(short)));
+               return 0;
+       } else {
+               /* A real frame */
+               tech_pvt->read_frame.datalen = samples;
+       }
+       return 1;
+}
+
+int skypiax_senddigit(private_t * tech_pvt, char digit)
+{
+       char msg_to_skype[1024];
+
+       DEBUGA_SKYPE("DIGIT received: %c\n", SKYPIAX_P_LOG, digit);
+       sprintf(msg_to_skype, "SET CALL %s DTMF %c", tech_pvt->skype_call_id, digit);
+       skypiax_signaling_write(tech_pvt, msg_to_skype);
+
+       return 0;
+}
+
+int skypiax_call(private_t * tech_pvt, char *rdest, int timeout)
+{
+       char msg_to_skype[1024];
+
+       //skypiax_sleep(5000);
+       DEBUGA_SKYPE("Calling Skype, rdest is: %s\n", SKYPIAX_P_LOG, rdest);
+       //skypiax_signaling_write(tech_pvt, "SET AGC OFF");
+       //skypiax_sleep(10000);
+       //skypiax_signaling_write(tech_pvt, "SET AEC OFF");
+       //skypiax_sleep(10000);
+
+       sprintf(msg_to_skype, "CALL %s", rdest);
+       if (skypiax_signaling_write(tech_pvt, msg_to_skype) < 0) {
+               ERRORA("failed to communicate with Skype client, now exit\n", SKYPIAX_P_LOG);
+               return -1;
+       }
+       return 0;
+}
+
+/***************************/
+/* PLATFORM SPECIFIC */
+/***************************/
+#if defined(WIN32) && !defined(__CYGWIN__)
+int skypiax_pipe_read(switch_file_t * pipe, short *buf, int howmany)
+{
+       switch_size_t quantity;
+
+       quantity = howmany;
+
+       switch_file_read(pipe, buf, &quantity);
+
+       howmany = quantity;
+
+       return howmany;
+}
+
+int skypiax_pipe_write(switch_file_t * pipe, short *buf, int howmany)
+{
+       switch_size_t quantity;
+
+       quantity = howmany;
+
+       switch_file_write(pipe, buf, &quantity);
+
+       howmany = quantity;
+
+       return howmany;
+}
+
+int skypiax_close_socket(unsigned int fd)
+{
+       int res;
+
+       res = closesocket(fd);
+
+       return res;
+}
+
+int skypiax_audio_init(private_t * tech_pvt)
+{
+       switch_status_t rv;
+       rv = switch_file_pipe_create(&tech_pvt->audiopipe_srv[0], &tech_pvt->audiopipe_srv[1], skypiax_module_pool);
+       rv = switch_file_pipe_create(&tech_pvt->audiopipe_cli[0], &tech_pvt->audiopipe_cli[1], skypiax_module_pool);
+       return 0;
+}
+#else /* WIN32 */
+int skypiax_pipe_read(int pipe, short *buf, int howmany)
+{
+       howmany = read(pipe, buf, howmany);
+       return howmany;
+}
+
+int skypiax_pipe_write(int pipe, short *buf, int howmany)
+{
+       if (buf) {
+               howmany = write(pipe, buf, howmany);
+               return howmany;
+       } else {
+               return 0;
+       }
+}
+
+int skypiax_close_socket(unsigned int fd)
+{
+       int res;
+
+       res = close(fd);
+
+       return res;
+}
+
+int skypiax_audio_init(private_t * tech_pvt)
+{
+       if (pipe(tech_pvt->audiopipe_srv)) {
+               fcntl(tech_pvt->audiopipe_srv[0], F_SETFL, O_NONBLOCK);
+               fcntl(tech_pvt->audiopipe_srv[1], F_SETFL, O_NONBLOCK);
+       }
+       if (pipe(tech_pvt->audiopipe_cli)) {
+               fcntl(tech_pvt->audiopipe_cli[0], F_SETFL, O_NONBLOCK);
+               fcntl(tech_pvt->audiopipe_cli[1], F_SETFL, O_NONBLOCK);
+       }
+
+/* this pipe is the audio fd for asterisk to poll on during a call. FS do not use it */
+       tech_pvt->skypiax_sound_capt_fd = tech_pvt->audiopipe_srv[0];
+
+       return 0;
+}
+#endif /* WIN32 */
+
+#ifdef WIN32
+
+enum {
+       SKYPECONTROLAPI_ATTACH_SUCCESS = 0,     /*  Client is successfully 
+                                                                                  attached and API window handle can be found
+                                                                                  in wParam parameter */
+       SKYPECONTROLAPI_ATTACH_PENDING_AUTHORIZATION = 1,       /*  Skype has acknowledged
+                                                                                                                  connection request and is waiting
+                                                                                                                  for confirmation from the user. */
+       /*  The client is not yet attached 
+        * and should wait for SKYPECONTROLAPI_ATTACH_SUCCESS message */
+       SKYPECONTROLAPI_ATTACH_REFUSED = 2,     /*  User has explicitly
+                                                                                  denied access to client */
+       SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE = 3,       /*  API is not available
+                                                                                                  at the moment.
+                                                                                                  For example, this happens when no user
+                                                                                                  is currently logged in. */
+       /*  Client should wait for 
+        * SKYPECONTROLAPI_ATTACH_API_AVAILABLE 
+        * broadcast before making any further */
+       /*  connection attempts. */
+       SKYPECONTROLAPI_ATTACH_API_AVAILABLE = 0x8001
+};
+
+/* Visual C do not have strsep? */
+char
+    *strsep(char **stringp, const char *delim)
+{
+       char *res;
+
+       if (!stringp || !*stringp || !**stringp)
+               return (char *) 0;
+
+       res = *stringp;
+       while (**stringp && !strchr(delim, **stringp))
+               ++(*stringp);
+
+       if (**stringp) {
+               **stringp = '\0';
+               ++(*stringp);
+       }
+
+       return res;
+}
+
+int skypiax_signaling_write(private_t * tech_pvt, char *msg_to_skype)
+{
+       static char acInputRow[1024];
+       COPYDATASTRUCT oCopyData;
+
+       DEBUGA_SKYPE("SENDING: |||%s||||\n", SKYPIAX_P_LOG, msg_to_skype);
+
+       sprintf(acInputRow, "%s", msg_to_skype);
+       DEBUGA_SKYPE("acInputRow: |||%s||||\n", SKYPIAX_P_LOG, acInputRow);
+       /*  send command to skype */
+       oCopyData.dwData = 0;
+       oCopyData.lpData = acInputRow;
+       oCopyData.cbData = strlen(acInputRow) + 1;
+       if (oCopyData.cbData != 1) {
+               if (SendMessage
+                       (tech_pvt->SkypiaxHandles.win32_hGlobal_SkypeAPIWindowHandle, WM_COPYDATA,
+                        (WPARAM) tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle, (LPARAM) & oCopyData) == FALSE) {
+                       ERRORA("Sending message failed - probably Skype crashed.\n\nPlease shutdown Skypiax, then launch Skypiax and try again.\n", SKYPIAX_P_LOG);
+                       return -1;
+               }
+       }
+
+       return 0;
+
+}
+
+LRESULT APIENTRY skypiax_present(HWND hWindow, UINT uiMessage, WPARAM uiParam, LPARAM ulParam)
+{
+       LRESULT lReturnCode;
+       int fIssueDefProc;
+       private_t *tech_pvt = NULL;
+
+       lReturnCode = 0;
+       fIssueDefProc = 0;
+       tech_pvt = (private_t *) GetWindowLong(hWindow, GWL_USERDATA);
+       if (!running)
+               return lReturnCode;
+       switch (uiMessage) {
+       case WM_CREATE:
+               tech_pvt = (private_t *) ((LPCREATESTRUCT) ulParam)->lpCreateParams;
+               SetWindowLong(hWindow, GWL_USERDATA, (LONG) tech_pvt);
+               DEBUGA_SKYPE("got CREATE\n", SKYPIAX_P_LOG);
+               break;
+       case WM_DESTROY:
+               DEBUGA_SKYPE("got DESTROY\n", SKYPIAX_P_LOG);
+               tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle = NULL;
+               PostQuitMessage(0);
+               break;
+       case WM_COPYDATA:
+               if (tech_pvt->SkypiaxHandles.win32_hGlobal_SkypeAPIWindowHandle == (HWND) uiParam) {
+                       unsigned int howmany;
+                       char msg_from_skype[2048];
+
+                       PCOPYDATASTRUCT poCopyData = (PCOPYDATASTRUCT) ulParam;
+
+                       memset(msg_from_skype, '\0', sizeof(msg_from_skype));
+                       skypiax_strncpy(msg_from_skype, (const char *) poCopyData->lpData, sizeof(msg_from_skype) - 2);
+
+                       howmany = strlen(msg_from_skype) + 1;
+                       howmany = skypiax_pipe_write(tech_pvt->SkypiaxHandles.fdesc[1], (short *) msg_from_skype, howmany);
+                       //DEBUGA_SKYPE("From Skype API: %s\n", SKYPIAX_P_LOG, msg_from_skype);
+                       lReturnCode = 1;
+               }
+               break;
+       default:
+               if (tech_pvt && tech_pvt->SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIAttach) {
+                       if (uiMessage == tech_pvt->SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIAttach) {
+                               switch (ulParam) {
+                               case SKYPECONTROLAPI_ATTACH_SUCCESS:
+                                       if (!tech_pvt->SkypiaxHandles.currentuserhandle) {
+                                               //DEBUGA_SKYPE("\n\n\tConnected to Skype API!\n", SKYPIAX_P_LOG);
+                                               tech_pvt->SkypiaxHandles.api_connected = 1;
+                                               tech_pvt->SkypiaxHandles.win32_hGlobal_SkypeAPIWindowHandle = (HWND) uiParam;
+                                               tech_pvt->SkypiaxHandles.win32_hGlobal_SkypeAPIWindowHandle = tech_pvt->SkypiaxHandles.win32_hGlobal_SkypeAPIWindowHandle;
+                                       }
+                                       break;
+                               case SKYPECONTROLAPI_ATTACH_PENDING_AUTHORIZATION:
+                                       //DEBUGA_SKYPE ("\n\n\tIf I do not (almost) immediately connect to Skype API,\n\tplease give the Skype client authorization to be connected \n\tby Asterisk and to not ask you again.\n\n", SKYPIAX_P_LOG);
+                                       skypiax_sleep(5000);
+#if 0
+                                       if (!tech_pvt->SkypiaxHandles.currentuserhandle) {
+                                               SendMessage(HWND_BROADCAST,
+                                                                       tech_pvt->SkypiaxHandles.
+                                                                       win32_uiGlobal_MsgID_SkypeControlAPIDiscover, (WPARAM) tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle, 0);
+                                       }
+#endif
+                                       break;
+                               case SKYPECONTROLAPI_ATTACH_REFUSED:
+                                       ERRORA("Skype client refused to be connected by Skypiax!\n", SKYPIAX_P_LOG);
+                                       break;
+                               case SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE:
+                                       ERRORA("Skype API not (yet?) available\n", SKYPIAX_P_LOG);
+                                       break;
+                               case SKYPECONTROLAPI_ATTACH_API_AVAILABLE:
+                                       DEBUGA_SKYPE("Skype API available\n", SKYPIAX_P_LOG);
+                                       skypiax_sleep(5000);
+#if 0
+                                       if (!tech_pvt->SkypiaxHandles.currentuserhandle) {
+                                               SendMessage(HWND_BROADCAST,
+                                                                       tech_pvt->SkypiaxHandles.
+                                                                       win32_uiGlobal_MsgID_SkypeControlAPIDiscover, (WPARAM) tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle, 0);
+                                       }
+#endif
+                                       break;
+                               default:
+                                       WARNINGA("GOT AN UNKNOWN SKYPE WINDOWS MSG\n", SKYPIAX_P_LOG);
+                               }
+                               lReturnCode = 1;
+                               break;
+                       }
+               }
+               fIssueDefProc = 1;
+               break;
+       }
+       if (fIssueDefProc)
+               lReturnCode = DefWindowProc(hWindow, uiMessage, uiParam, ulParam);
+       return (lReturnCode);
+}
+
+int win32_Initialize_CreateWindowClass(private_t * tech_pvt)
+{
+       unsigned char *paucUUIDString;
+       RPC_STATUS lUUIDResult;
+       int fReturnStatus;
+       UUID oUUID;
+
+       fReturnStatus = 0;
+       lUUIDResult = UuidCreate(&oUUID);
+       tech_pvt->SkypiaxHandles.win32_hInit_ProcessHandle = (HINSTANCE) OpenProcess(PROCESS_DUP_HANDLE, FALSE, GetCurrentProcessId());
+       if (tech_pvt->SkypiaxHandles.win32_hInit_ProcessHandle != NULL && (lUUIDResult == RPC_S_OK || lUUIDResult == RPC_S_UUID_LOCAL_ONLY)) {
+               if (UuidToString(&oUUID, &paucUUIDString) == RPC_S_OK) {
+                       WNDCLASS oWindowClass;
+
+                       strcpy(tech_pvt->SkypiaxHandles.win32_acInit_WindowClassName, "Skype-API-Skypiax-");
+                       strcat(tech_pvt->SkypiaxHandles.win32_acInit_WindowClassName, (char *) paucUUIDString);
+
+                       oWindowClass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
+                       oWindowClass.lpfnWndProc = (WNDPROC) & skypiax_present;
+                       oWindowClass.cbClsExtra = 0;
+                       oWindowClass.cbWndExtra = 0;
+                       oWindowClass.hInstance = tech_pvt->SkypiaxHandles.win32_hInit_ProcessHandle;
+                       oWindowClass.hIcon = NULL;
+                       oWindowClass.hCursor = NULL;
+                       oWindowClass.hbrBackground = NULL;
+                       oWindowClass.lpszMenuName = NULL;
+                       oWindowClass.lpszClassName = tech_pvt->SkypiaxHandles.win32_acInit_WindowClassName;
+
+                       if (RegisterClass(&oWindowClass) != 0)
+                               fReturnStatus = 1;
+
+                       RpcStringFree(&paucUUIDString);
+               }
+       }
+       if (fReturnStatus == 0)
+               CloseHandle(tech_pvt->SkypiaxHandles.win32_hInit_ProcessHandle);
+       tech_pvt->SkypiaxHandles.win32_hInit_ProcessHandle = NULL;
+       return (fReturnStatus);
+}
+
+void win32_DeInitialize_DestroyWindowClass(private_t * tech_pvt)
+{
+       UnregisterClass(tech_pvt->SkypiaxHandles.win32_acInit_WindowClassName, tech_pvt->SkypiaxHandles.win32_hInit_ProcessHandle);
+       CloseHandle(tech_pvt->SkypiaxHandles.win32_hInit_ProcessHandle);
+       tech_pvt->SkypiaxHandles.win32_hInit_ProcessHandle = NULL;
+}
+
+int win32_Initialize_CreateMainWindow(private_t * tech_pvt)
+{
+       tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle =
+               CreateWindowEx(WS_EX_APPWINDOW | WS_EX_WINDOWEDGE,
+                                          tech_pvt->SkypiaxHandles.win32_acInit_WindowClassName, "",
+                                          WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT,
+                                          128, 128, NULL, 0, tech_pvt->SkypiaxHandles.win32_hInit_ProcessHandle, tech_pvt);
+       return (tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle != NULL ? 1 : 0);
+}
+
+void win32_DeInitialize_DestroyMainWindow(private_t * tech_pvt)
+{
+       if (tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle != NULL)
+               DestroyWindow(tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle), tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle = NULL;
+}
+
+void *skypiax_do_skypeapi_thread_func(void *obj)
+{
+       private_t *tech_pvt = obj;
+#if defined(WIN32) && !defined(__CYGWIN__)
+       switch_status_t rv;
+
+       switch_file_pipe_create(&tech_pvt->SkypiaxHandles.fdesc[0], &tech_pvt->SkypiaxHandles.fdesc[1], skypiax_module_pool);
+       rv = switch_file_pipe_create(&tech_pvt->SkypiaxHandles.fdesc[0], &tech_pvt->SkypiaxHandles.fdesc[1], skypiax_module_pool);
+#else /* WIN32 */
+       if (pipe(tech_pvt->SkypiaxHandles.fdesc)) {
+               fcntl(tech_pvt->SkypiaxHandles.fdesc[0], F_SETFL, O_NONBLOCK);
+               fcntl(tech_pvt->SkypiaxHandles.fdesc[1], F_SETFL, O_NONBLOCK);
+       }
+#endif /* WIN32 */
+
+       tech_pvt->SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIAttach = RegisterWindowMessage("SkypeControlAPIAttach");
+       tech_pvt->SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIDiscover = RegisterWindowMessage("SkypeControlAPIDiscover");
+
+       skypiax_sleep(200000);          //0,2 sec
+
+       if (tech_pvt->SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIAttach != 0
+               && tech_pvt->SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIDiscover != 0) {
+               if (win32_Initialize_CreateWindowClass(tech_pvt)) {
+                       if (win32_Initialize_CreateMainWindow(tech_pvt)) {
+                               if (SendMessage
+                                       (HWND_BROADCAST,
+                                        tech_pvt->SkypiaxHandles.win32_uiGlobal_MsgID_SkypeControlAPIDiscover,
+                                        (WPARAM) tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle, 0) != 0) {
+                                       tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle = tech_pvt->SkypiaxHandles.win32_hInit_MainWindowHandle;
+                                       while (running && tech_pvt->running) {
+                                               MSG oMessage;
+                                               if (!(running && tech_pvt->running))
+                                                       break;
+                                               while (GetMessage(&oMessage, 0, 0, 0)) {
+                                                       TranslateMessage(&oMessage);
+                                                       DispatchMessage(&oMessage);
+                                               }
+                                       }
+                               }
+                               win32_DeInitialize_DestroyMainWindow(tech_pvt);
+                       }
+                       win32_DeInitialize_DestroyWindowClass(tech_pvt);
+               }
+       }
+
+       return NULL;
+}
+
+#else /* NOT WIN32 */
+int X11_errors_handler(Display * dpy, XErrorEvent * err)
+{
+       private_t *tech_pvt = NULL;
+       (void) dpy;
+
+       xerror = err->error_code;
+       ERRORA("Received error code %d from X Server\n\n", SKYPIAX_P_LOG, xerror);      ///FIXME why crash the entire skypiax? just crash the interface, instead
+       //running = 0;
+       return 0;                                       /*  ignore the error */
+}
+
+static void X11_errors_trap(void)
+{
+       xerror = 0;
+       old_handler = XSetErrorHandler(X11_errors_handler);
+}
+
+static int X11_errors_untrap(void)
+{
+       XSetErrorHandler(old_handler);
+       return (xerror != BadValue) && (xerror != BadWindow);
+}
+
+int skypiax_send_message(private_t * tech_pvt, const char *message_P)
+{
+       struct SkypiaxHandles *SkypiaxHandles = &tech_pvt->SkypiaxHandles;
+       Window w_P = SkypiaxHandles->skype_win;
+       Display *disp = SkypiaxHandles->disp;
+       Window handle_P = SkypiaxHandles->win;
+       int ok;
+       //private_t *tech_pvt = NULL;
+
+
+       Atom atom1 = XInternAtom(disp, "SKYPECONTROLAPI_MESSAGE_BEGIN", False);
+       Atom atom2 = XInternAtom(disp, "SKYPECONTROLAPI_MESSAGE", False);
+       unsigned int pos = 0;
+       unsigned int len = strlen(message_P);
+       XEvent e;
+
+       memset(&e, 0, sizeof(e));
+       e.xclient.type = ClientMessage;
+       e.xclient.message_type = atom1; /*  leading message */
+       e.xclient.display = disp;
+       e.xclient.window = handle_P;
+       e.xclient.format = 8;
+
+       X11_errors_trap();
+       //XLockDisplay(disp);
+       do {
+               unsigned int i;
+               for (i = 0; i < 20 && i + pos <= len; ++i)
+                       e.xclient.data.b[i] = message_P[i + pos];
+               XSendEvent(disp, w_P, False, 0, &e);
+
+               e.xclient.message_type = atom2; /*  following messages */
+               pos += i;
+       } while (pos <= len);
+
+       XSync(disp, False);
+       ok = X11_errors_untrap();
+
+       if (!ok) {
+               ERRORA("Sending message failed with status %d\n", SKYPIAX_P_LOG, xerror);
+               tech_pvt->running = 0;
+               return 0;
+       }
+       //XUnlockDisplay(disp);
+
+       return 1;
+}
+
+int skypiax_signaling_write(private_t * tech_pvt, char *msg_to_skype)
+{
+
+       DEBUGA_SKYPE("SENDING: |||%s||||\n", SKYPIAX_P_LOG, msg_to_skype);
+
+
+       if (!skypiax_send_message(tech_pvt, msg_to_skype)) {
+               ERRORA
+                       ("Sending message failed - probably Skype crashed.\n\nPlease shutdown Skypiax, then restart Skype, then launch Skypiax and try again.\n",
+                        SKYPIAX_P_LOG);
+               return -1;
+       }
+
+       return 0;
+
+}
+
+int skypiax_present(struct SkypiaxHandles *SkypiaxHandles)
+{
+       Atom skype_inst = XInternAtom(SkypiaxHandles->disp, "_SKYPE_INSTANCE", True);
+
+       Atom type_ret;
+       int format_ret;
+       unsigned long nitems_ret;
+       unsigned long bytes_after_ret;
+       unsigned char *prop;
+       int status;
+       private_t *tech_pvt = NULL;
+
+       X11_errors_trap();
+       //XLockDisplay(disp);
+       status =
+               XGetWindowProperty(SkypiaxHandles->disp, DefaultRootWindow(SkypiaxHandles->disp),
+                                                  skype_inst, 0, 1, False, XA_WINDOW, &type_ret, &format_ret, &nitems_ret, &bytes_after_ret, &prop);
+       //XUnlockDisplay(disp);
+       X11_errors_untrap();
+
+       /*  sanity check */
+       if (status != Success || format_ret != 32 || nitems_ret != 1) {
+               SkypiaxHandles->skype_win = (Window) - 1;
+               DEBUGA_SKYPE("Skype instance not found\n", SKYPIAX_P_LOG);
+               running = 0;
+               SkypiaxHandles->api_connected = 0;
+               return 0;
+       }
+
+       SkypiaxHandles->skype_win = *(const unsigned long *) prop & 0xffffffff;
+       DEBUGA_SKYPE("Skype instance found with id #%d\n", SKYPIAX_P_LOG, (unsigned int) SkypiaxHandles->skype_win);
+       SkypiaxHandles->api_connected = 1;
+       return 1;
+}
+
+void skypiax_clean_disp(void *data)
+{
+
+       int *dispptr;
+       int disp;
+       private_t *tech_pvt = NULL;
+
+       dispptr = data;
+       disp = *dispptr;
+
+       if (disp) {
+               DEBUGA_SKYPE("to be destroyed disp %d\n", SKYPIAX_P_LOG, disp);
+               close(disp);
+               DEBUGA_SKYPE("destroyed disp\n", SKYPIAX_P_LOG);
+       } else {
+               DEBUGA_SKYPE("NOT destroyed disp\n", SKYPIAX_P_LOG);
+       }
+       DEBUGA_SKYPE("OUT destroyed disp\n", SKYPIAX_P_LOG);
+       skypiax_sleep(1000);
+}
+
+void *skypiax_do_skypeapi_thread_func(void *obj)
+{
+
+       private_t *tech_pvt = obj;
+       struct SkypiaxHandles *SkypiaxHandles;
+       char buf[512];
+       Display *disp = NULL;
+       Window root = -1;
+       Window win = -1;
+       int xfd;
+
+       if (!strlen(tech_pvt->X11_display))
+               strcpy(tech_pvt->X11_display, getenv("DISPLAY"));
+
+       if (!tech_pvt->tcp_srv_port)
+               tech_pvt->tcp_srv_port = 10160;
+
+       if (!tech_pvt->tcp_cli_port)
+               tech_pvt->tcp_cli_port = 10161;
+
+       if (pipe(tech_pvt->SkypiaxHandles.fdesc)) {
+               fcntl(tech_pvt->SkypiaxHandles.fdesc[0], F_SETFL, O_NONBLOCK);
+               fcntl(tech_pvt->SkypiaxHandles.fdesc[1], F_SETFL, O_NONBLOCK);
+       }
+       SkypiaxHandles = &tech_pvt->SkypiaxHandles;
+       disp = XOpenDisplay(tech_pvt->X11_display);
+       if (!disp) {
+               ERRORA("Cannot open X Display '%s', exiting skype thread\n", SKYPIAX_P_LOG, tech_pvt->X11_display);
+               running = 0;
+               return NULL;
+       } else {
+               DEBUGA_SKYPE("X Display '%s' opened\n", SKYPIAX_P_LOG, tech_pvt->X11_display);
+       }
+
+       xfd = XConnectionNumber(disp);
+       fcntl(xfd, F_SETFD, FD_CLOEXEC);
+
+       SkypiaxHandles->disp = disp;
+
+       if (skypiax_present(SkypiaxHandles)) {
+               root = DefaultRootWindow(disp);
+               win = XCreateSimpleWindow(disp, root, 0, 0, 1, 1, 0, BlackPixel(disp, DefaultScreen(disp)), BlackPixel(disp, DefaultScreen(disp)));
+
+               SkypiaxHandles->win = win;
+
+               snprintf(buf, 512, "NAME skypiax");
+
+               if (!skypiax_send_message(tech_pvt, buf)) {
+                       ERRORA("Sending message failed - probably Skype crashed. Please run/restart Skype manually and launch Skypiax again\n", SKYPIAX_P_LOG);
+                       running = 0;
+                       //if(disp)
+                       //XCloseDisplay(disp);
+                       return NULL;
+               }
+
+               snprintf(buf, 512, "PROTOCOL 7");
+               if (!skypiax_send_message(tech_pvt, buf)) {
+                       ERRORA("Sending message failed - probably Skype crashed. Please run/restart Skype manually and launch Skypiax again\n", SKYPIAX_P_LOG);
+                       running = 0;
+                       //if(disp)
+                       //XCloseDisplay(disp);
+                       return NULL;
+               }
+
+               {
+                       /* perform an events loop */
+                       XEvent an_event;
+                       char buf[21];           /*  can't be longer */
+                       char buffer[17000];
+                       char continuebuffer[17000];
+                       char *b;
+                       int i;
+                       int continue_is_broken = 0;
+                       int there_were_continues = 0;
+                       Atom atom_begin = XInternAtom(disp, "SKYPECONTROLAPI_MESSAGE_BEGIN", False);
+                       Atom atom_continue = XInternAtom(disp, "SKYPECONTROLAPI_MESSAGE", False);
+
+                       memset(buffer, '\0', 17000);
+                       memset(continuebuffer, '\0', 17000);
+                       b = buffer;
+
+                       while (running && tech_pvt->running) {
+                               XNextEvent(disp, &an_event);
+                               if (!(running && tech_pvt->running))
+                                       break;
+                               switch (an_event.type) {
+                               case ClientMessage:
+
+                                       if (an_event.xclient.format != 8) {
+                                               skypiax_sleep(1000);    //0.1 msec
+                                               break;
+                                       }
+
+                                       for (i = 0; i < 20 && an_event.xclient.data.b[i] != '\0'; ++i)
+                                               buf[i] = an_event.xclient.data.b[i];
+
+                                       buf[i] = '\0';
+
+                                       //DEBUGA_SKYPE ("BUF=|||%s|||\n", SKYPIAX_P_LOG, buf);
+
+                                       if (an_event.xclient.message_type == atom_begin) {
+                                               //DEBUGA_SKYPE ("BEGIN BUF=|||%s|||\n", SKYPIAX_P_LOG, buf);
+
+                                               if (strlen(buffer)) {
+                                                       unsigned int howmany;
+                                                       howmany = strlen(b) + 1;
+                                                       howmany = write(SkypiaxHandles->fdesc[1], b, howmany);
+                                                       WARNINGA
+                                                               ("A begin atom while the previous message is not closed???? value of previous message (between vertical bars) is=|||%s|||, will be lost\n",
+                                                                SKYPIAX_P_LOG, buffer);
+                                                       memset(buffer, '\0', 17000);
+                                               }
+                                               if (continue_is_broken) {
+                                                       continue_is_broken = 0;
+                                                       there_were_continues = 1;
+                                               }
+                                       }
+                                       if (an_event.xclient.message_type == atom_continue) {
+                                               //DEBUGA_SKYPE ("CONTINUE BUF=|||%s|||\n", SKYPIAX_P_LOG, buf);
+
+                                               if (!strlen(buffer)) {
+                                                       DEBUGA_SKYPE
+                                                               ("Got a 'continue' XAtom without a previous 'begin'. It's value (between vertical bars) is=|||%s|||, let's store it and hope next 'begin' will be the good one\n",
+                                                                SKYPIAX_P_LOG, buf);
+                                                       strcat(continuebuffer, buf);
+                                                       continue_is_broken = 1;
+                                                       if (!strncmp(buf, "ognised identity", 15)) {
+                                                               WARNINGA
+                                                                       ("Got a 'continue' XAtom without a previous 'begin'. It's value (between vertical bars) is=|||%s|||. Let's introduce a 1 second delay.\n",
+                                                                        SKYPIAX_P_LOG, buf);
+                                                               skypiax_sleep(1000000); //1 sec
+                                                       }
+                                                       skypiax_sleep(1000);    //0.1 msec
+                                                       break;
+                                               }
+                                       }
+                                       if (continue_is_broken) {
+                                               XFlush(disp);
+                                               skypiax_sleep(1000);    //0.1 msec
+                                               continue;
+                                       }
+                                       //DEBUGA_SKYPE ("i=%d, buffer=|||%s|||\n", SKYPIAX_P_LOG, i, buffer);
+                                       strcat(buffer, buf);
+                                       //DEBUGA_SKYPE ("i=%d, buffer=|||%s|||\n", SKYPIAX_P_LOG, i, buffer);
+                                       strcat(buffer, continuebuffer);
+                                       //DEBUGA_SKYPE ("i=%d, buffer=|||%s|||\n", SKYPIAX_P_LOG, i, buffer);
+                                       memset(continuebuffer, '\0', 17000);
+
+                                       if (i < 20 || there_were_continues) {   /* last fragment */
+                                               unsigned int howmany;
+
+                                               howmany = strlen(b) + 1;
+
+                                               howmany = write(SkypiaxHandles->fdesc[1], b, howmany);
+                                               //DEBUGA_SKYPE ("RECEIVED=|||%s|||\n", SKYPIAX_P_LOG, buffer);
+                                               memset(buffer, '\0', 17000);
+                                               XFlush(disp);
+                                               there_were_continues = 0;
+                                       }
+
+                                       skypiax_sleep(1000);    //0.1 msec
+                                       break;
+                               default:
+                                       skypiax_sleep(1000);    //0.1 msec
+                                       break;
+                               }
+                       }
+               }
+       } else {
+               ERRORA("Skype is not running, maybe crashed. Please run/restart Skype and relaunch Skypiax\n", SKYPIAX_P_LOG);
+               running = 0;
+               //if(disp)
+               //XCloseDisplay(disp);
+               return NULL;
+       }
+       //running = 0;
+       //if(disp)
+       //XCloseDisplay(disp);
+       return NULL;
+
+}
+#endif // WIN32