<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[Freeswitch-trunk][14634] </title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<div id="header">FreeSWITCH Subversion</div>
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://fisheye.freeswitch.org/changelog/FreeSWITCH?cs=14634">14634</a></dd>
<dt>Author</dt> <dd>gmaruzz</dd>
<dt>Date</dt> <dd>2009-08-25 13:58:31 -0500 (Tue, 25 Aug 2009)</dd>
</dl>

<h3>Log Message</h3>
<pre>celliax: initialize alsa</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#freeswitchbranchesgmaruzzmod_celliaxMakefile">freeswitch/branches/gmaruzz/mod_celliax/Makefile</a></li>
<li><a href="#freeswitchbranchesgmaruzzmod_celliaxcelliaxh">freeswitch/branches/gmaruzz/mod_celliax/celliax.h</a></li>
<li><a href="#freeswitchbranchesgmaruzzmod_celliaxcelliax_protocolc">freeswitch/branches/gmaruzz/mod_celliax/celliax_protocol.c</a></li>
<li><a href="#freeswitchbranchesgmaruzzmod_celliaxmod_celliaxc">freeswitch/branches/gmaruzz/mod_celliax/mod_celliax.c</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="freeswitchbranchesgmaruzzmod_celliaxMakefile"></a>
<div class="modfile"><h4>Modified: freeswitch/branches/gmaruzz/mod_celliax/Makefile (14633 => 14634)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/branches/gmaruzz/mod_celliax/Makefile        2009-08-25 11:51:55 UTC (rev 14633)
+++ freeswitch/branches/gmaruzz/mod_celliax/Makefile        2009-08-25 18:58:31 UTC (rev 14634)
</span><span class="lines">@@ -1,6 +1,6 @@
</span><span class="cx"> MODNAME=mod_celliax
</span><span class="cx"> SVNDEF := -D'SKYPIAX_SVN_VERSION=&quot;$(shell svnversion -n .)&quot;'
</span><span class="cx"> LOCAL_CFLAGS += $(SVNDEF)
</span><del>-LOCAL_LDFLAGS=-lX11
</del><ins>+LOCAL_LDFLAGS=-lX11 -lasound
</ins><span class="cx"> LOCAL_OBJS=celliax_protocol.o
</span><span class="cx"> include ../../../../build/modmake.rules
</span></span></pre></div>
<a id="freeswitchbranchesgmaruzzmod_celliaxcelliaxh"></a>
<div class="modfile"><h4>Modified: freeswitch/branches/gmaruzz/mod_celliax/celliax.h (14633 => 14634)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/branches/gmaruzz/mod_celliax/celliax.h        2009-08-25 11:51:55 UTC (rev 14633)
+++ freeswitch/branches/gmaruzz/mod_celliax/celliax.h        2009-08-25 18:58:31 UTC (rev 14634)
</span><span class="lines">@@ -34,12 +34,35 @@
</span><span class="cx">  *
</span><span class="cx">  */
</span><span class="cx"> 
</span><ins>+#undef GIOVA48
+
+#ifndef GIOVA48
+#define SAMPLES_PER_FRAME 160
+#else // GIOVA48
+#define SAMPLES_PER_FRAME 960
+#endif // GIOVA48
+
+
+#ifndef GIOVA48
+#define     SKYPIAX_FRAME_SIZE   160
+#else //GIOVA48
+#define     SKYPIAX_FRAME_SIZE   960
+#endif //GIOVA48
+#define     SAMPLERATE_SKYPIAX   8000
+
+#define CELLIAX_ALSA
</ins><span class="cx"> #include &lt;switch.h&gt;
</span><span class="cx"> #include &lt;switch_version.h&gt;
</span><span class="cx"> #include &lt;termios.h&gt;
</span><span class="cx"> #include &lt;sys/ioctl.h&gt;
</span><span class="cx"> #include &lt;iconv.h&gt;
</span><ins>+#ifdef CELLIAX_ALSA
+#define ALSA_PCM_NEW_HW_PARAMS_API
+#define ALSA_PCM_NEW_SW_PARAMS_API
+#include &lt;alsa/asoundlib.h&gt;
+#endif /* CELLIAX_ALSA */
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx"> #ifndef WIN32
</span><span class="cx"> #include &lt;sys/time.h&gt;
</span><span class="cx"> #include &lt;X11/Xlib.h&gt;
</span><span class="lines">@@ -64,8 +87,8 @@
</span><span class="cx"> //FIXME FIXME FIXME #define AT_MESG_MAX_LINES 256   /* 256 lines, so it can contains the results of AT+CLAC, that gives all the AT commands the phone supports */
</span><span class="cx"> #define AT_MESG_MAX_LINES 20   /* 256 lines, so it can contains the results of AT+CLAC, that gives all the AT commands the phone supports */
</span><span class="cx"> 
</span><del>-#define SAMPLERATE_SKYPIAX 16000
-#define SAMPLES_PER_FRAME SAMPLERATE_SKYPIAX/50
</del><ins>+//#define SAMPLERATE_SKYPIAX 16000
+//#define SAMPLES_PER_FRAME SAMPLERATE_SKYPIAX/50
</ins><span class="cx"> 
</span><span class="cx"> #ifndef SKYPIAX_SVN_VERSION
</span><span class="cx"> #define SKYPIAX_SVN_VERSION SWITCH_VERSION_REVISION
</span><span class="lines">@@ -256,8 +279,8 @@
</span><span class="cx">         switch_thread_t *tcp_cli_thread;
</span><span class="cx">         switch_thread_t *celliax_signaling_thread;
</span><span class="cx">         switch_thread_t *celliax_api_thread;
</span><del>-        short audiobuf[SAMPLES_PER_FRAME];
-        int audiobuf_is_loaded;
</del><ins>+        //short audiobuf[SAMPLES_PER_FRAME];
+        //int audiobuf_is_loaded;
</ins><span class="cx"> 
</span><span class="cx">         //int phonebook_listing;
</span><span class="cx">         //int phonebook_querying;
</span><span class="lines">@@ -389,6 +412,24 @@
</span><span class="cx"> 
</span><span class="cx">   struct timeval ringtime;
</span><span class="cx">   ciapa_t *owner;
</span><ins>+#ifdef CELLIAX_ALSA
+  snd_pcm_t *alsac;             /*!&lt; \brief handle of the ALSA capture audio device */
+  snd_pcm_t *alsap;             /*!&lt; \brief handle of the ALSA playback audio device */
+  char alsacname[50];           /*!&lt; \brief name of the ALSA capture audio device */
+  char alsapname[50];           /*!&lt; \brief name of the ALSA playback audio device */
+  int alsa_period_size;         /*!&lt; \brief ALSA period_size, in byte */
+  int alsa_periods_in_buffer;   /*!&lt; \brief how many periods in ALSA buffer, to calculate buffer_size */
+  unsigned long int alsa_buffer_size;   /*!&lt; \brief ALSA buffer_size, in byte */
+  int alsawrite_filled;
+  int alsa_capture_is_mono;
+  int alsa_play_is_mono;
+  struct pollfd pfd;
+#endif// CELLIAX_ALSA
+
+  time_t audio_play_reset_timestamp;
+  int audio_play_reset_period;
+
+
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> typedef struct private_object private_t;
</span><span class="lines">@@ -396,7 +437,6 @@
</span><span class="cx"> void *SWITCH_THREAD_FUNC celliax_api_thread_func(switch_thread_t * thread, void *obj);
</span><span class="cx"> int celliax_audio_read(private_t * tech_pvt);
</span><span class="cx"> int celliax_audio_init(private_t * tech_pvt);
</span><del>-int celliax_signaling_write(private_t * tech_pvt, char *msg_to_skype);
</del><span class="cx"> int celliax_signaling_read(private_t * tech_pvt);
</span><span class="cx"> 
</span><span class="cx"> int celliax_call(private_t * tech_pvt, char *idest, int timeout);
</span><span class="lines">@@ -414,7 +454,7 @@
</span><span class="cx"> int start_audio_threads(private_t * tech_pvt);
</span><span class="cx"> int new_inbound_channel(private_t * tech_pvt);
</span><span class="cx"> int outbound_channel_answered(private_t * tech_pvt);
</span><del>-int celliax_signaling_write(private_t * tech_pvt, char *msg_to_skype);
</del><ins>+//int celliax_signaling_write(private_t * tech_pvt, char *msg_to_skype);
</ins><span class="cx"> #if defined(WIN32) &amp;&amp; !defined(__CYGWIN__)
</span><span class="cx"> int celliax_pipe_read(switch_file_t * pipe, short *buf, int howmany);
</span><span class="cx"> int celliax_pipe_write(switch_file_t * pipe, short *buf, int howmany);
</span><span class="lines">@@ -499,3 +539,10 @@
</span><span class="cx"> int celliax_serial_hangup(private_t * tech_pvt);
</span><span class="cx"> int celliax_serial_hangup_AT(private_t * tech_pvt);
</span><span class="cx"> int celliax_hangup(private_t * tech_pvt);
</span><ins>+#ifdef CELLIAX_ALSA
+int alsa_init(private_t * tech_pvt);
+int alsa_shutdown(private_t * tech_pvt);
+snd_pcm_t *alsa_open_dev(private_t * tech_pvt, snd_pcm_stream_t stream);
+struct ast_frame *alsa_read(private_t * tech_pvt);
+int alsa_write(private_t * tech_pvt, struct ast_frame *f);
+#endif /* CELLIAX_ALSA */
</ins></span></pre></div>
<a id="freeswitchbranchesgmaruzzmod_celliaxcelliax_protocolc"></a>
<div class="modfile"><h4>Modified: freeswitch/branches/gmaruzz/mod_celliax/celliax_protocol.c (14633 => 14634)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/branches/gmaruzz/mod_celliax/celliax_protocol.c        2009-08-25 11:51:55 UTC (rev 14633)
+++ freeswitch/branches/gmaruzz/mod_celliax/celliax_protocol.c        2009-08-25 18:58:31 UTC (rev 14634)
</span><span class="lines">@@ -12,13 +12,14 @@
</span><span class="cx"> extern switch_memory_pool_t *celliax_module_pool;
</span><span class="cx"> extern switch_endpoint_interface_t *celliax_endpoint_interface;
</span><span class="cx"> #endif /* ASTERISK */
</span><del>-int samplerate_celliax = SAMPLERATE_SKYPIAX;
</del><ins>+//int samplerate_celliax = SAMPLERATE_SKYPIAX;
</ins><span class="cx"> 
</span><span class="cx"> extern int running;
</span><span class="cx"> int celliax_dir_entry_extension = 1;
</span><span class="cx"> 
</span><span class="cx"> int option_debug=100;
</span><span class="cx"> 
</span><ins>+#ifdef NOTDEF
</ins><span class="cx"> /*************************************/
</span><span class="cx"> /* suspicious globals FIXME */
</span><span class="cx"> #ifdef WIN32
</span><span class="lines">@@ -869,36 +870,6 @@
</span><span class="cx">         return 1;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-int celliax_senddigit(private_t * tech_pvt, char digit)
-{
-        char msg_to_skype[1024];
-
-        DEBUGA_SKYPE(&quot;DIGIT received: %c\n&quot;, SKYPIAX_P_LOG, digit);
-        sprintf(msg_to_skype, &quot;SET CALL %s DTMF %c&quot;, tech_pvt-&gt;skype_call_id, digit);
-        celliax_signaling_write(tech_pvt, msg_to_skype);
-
-        return 0;
-}
-
-int celliax_call(private_t * tech_pvt, char *rdest, int timeout)
-{
-        char msg_to_skype[1024];
-
-        //celliax_sleep(5000);
-        DEBUGA_SKYPE(&quot;Calling Skype, rdest is: %s\n&quot;, SKYPIAX_P_LOG, rdest);
-        //celliax_signaling_write(tech_pvt, &quot;SET AGC OFF&quot;);
-        //celliax_sleep(10000);
-        //celliax_signaling_write(tech_pvt, &quot;SET AEC OFF&quot;);
-        //celliax_sleep(10000);
-
-        sprintf(msg_to_skype, &quot;CALL %s&quot;, rdest);
-        if (celliax_signaling_write(tech_pvt, msg_to_skype) &lt; 0) {
-                ERRORA(&quot;failed to communicate with Skype client, now exit\n&quot;, SKYPIAX_P_LOG);
-                return -1;
-        }
-        return 0;
-}
-
</del><span class="cx"> /***************************/
</span><span class="cx"> /* PLATFORM SPECIFIC */
</span><span class="cx"> /***************************/
</span><span class="lines">@@ -1395,13 +1366,13 @@
</span><span class="cx"> #endif // WIN32
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+#endif //NOTDEF
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-
</del><span class="cx"> int celliax_serial_init(private_t *tech_pvt, speed_t controldevice_speed)
</span><span class="cx"> {
</span><span class="cx">   int fd;
</span><span class="lines">@@ -3800,3 +3771,810 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> #endif// NOTDEF
</span><ins>+
+
+#define SKYPIAX_ALSA
+#ifdef SKYPIAX_ALSA
+/*! \brief ALSA pcm format, according to endianess  */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+snd_pcm_format_t celliax_format = SND_PCM_FORMAT_S16_LE;
+#else
+snd_pcm_format_t celliax_format = SND_PCM_FORMAT_S16_BE;
+#endif
+
+/*!
+ * \brief Initialize the ALSA soundcard channels (capture AND playback) used by one interface (a multichannel soundcard can be used by multiple interfaces) 
+ * \param p the celliax_pvt of the interface
+ *
+ * This function call alsa_open_dev to initialize the ALSA soundcard for each channel (capture AND playback) used by one interface (a multichannel soundcard can be used by multiple interfaces). Called by sound_init
+ *
+ * \return zero on success, -1 on error.
+ */
+int alsa_init(private_t * tech_pvt)
+{
+  tech_pvt-&gt;alsac = alsa_open_dev(tech_pvt, SND_PCM_STREAM_CAPTURE);
+  if (!tech_pvt-&gt;alsac) {
+    ERRORA(&quot;Failed opening ALSA capture device: %s\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;alsacname);
+    if (alsa_shutdown(tech_pvt)) {
+      ERRORA(&quot;alsa_shutdown failed\n&quot;, SKYPIAX_P_LOG);
+      return -1;
+    }
+    return -1;
+  }
+  tech_pvt-&gt;alsap = alsa_open_dev(tech_pvt, SND_PCM_STREAM_PLAYBACK);
+  if (!tech_pvt-&gt;alsap) {
+    ERRORA(&quot;Failed opening ALSA playback device: %s\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;alsapname);
+    if (alsa_shutdown(tech_pvt)) {
+      ERRORA(&quot;alsa_shutdown failed\n&quot;, SKYPIAX_P_LOG);
+      return -1;
+    }
+    return -1;
+  }
+
+  /* make valgrind very happy */
+  snd_config_update_free_global();
+  return 0;
+}
+
+/*!
+ * \brief Shutdown the ALSA soundcard channels (input and output) used by one interface (a multichannel soundcard can be used by multiple interfaces) 
+ * \param p the celliax_pvt of the interface
+ *
+ * This function shutdown the ALSA soundcard channels (input and output) used by one interface (a multichannel soundcard can be used by multiple interfaces). Called by sound_init
+ *
+ * \return zero on success, -1 on error.
+ */
+
+int alsa_shutdown(private_t * tech_pvt)
+{
+
+  int err;
+
+  if (tech_pvt-&gt;alsap) {
+    err = snd_pcm_drop(tech_pvt-&gt;alsap);
+    if (err &lt; 0) {
+      ERRORA(&quot;device [%s], snd_pcm_drop failed with error '%s'\n&quot;, SKYPIAX_P_LOG,
+             tech_pvt-&gt;alsapname, snd_strerror(err));
+      return -1;
+    }
+    err = snd_pcm_close(tech_pvt-&gt;alsap);
+    if (err &lt; 0) {
+      ERRORA(&quot;device [%s], snd_pcm_close failed with error '%s'\n&quot;, SKYPIAX_P_LOG,
+             tech_pvt-&gt;alsapname, snd_strerror(err));
+      return -1;
+    }
+  }
+  if (tech_pvt-&gt;alsac) {
+    err = snd_pcm_drop(tech_pvt-&gt;alsac);
+    if (err &lt; 0) {
+      ERRORA(&quot;device [%s], snd_pcm_drop failed with error '%s'\n&quot;, SKYPIAX_P_LOG,
+             tech_pvt-&gt;alsacname, snd_strerror(err));
+      return -1;
+    }
+    err = snd_pcm_close(tech_pvt-&gt;alsac);
+    if (err &lt; 0) {
+      ERRORA(&quot;device [%s], snd_pcm_close failed with error '%s'\n&quot;, SKYPIAX_P_LOG,
+             tech_pvt-&gt;alsacname, snd_strerror(err));
+      return -1;
+    }
+  }
+
+  return 0;
+}
+
+/*!
+ * \brief Setup and open the ALSA device (capture OR playback) 
+ * \param p the celliax_pvt of the interface
+ * \param stream the ALSA capture/playback definition
+ *
+ * This function setup and open the ALSA device (capture OR playback). Called by alsa_init
+ *
+ * \return zero on success, -1 on error.
+ */
+snd_pcm_t *alsa_open_dev(private_t * tech_pvt, snd_pcm_stream_t stream)
+{
+
+  snd_pcm_t *handle = NULL;
+  snd_pcm_hw_params_t *params;
+  snd_pcm_sw_params_t *swparams;
+  snd_pcm_uframes_t buffer_size;
+  int err;
+  size_t n;
+  //snd_pcm_uframes_t xfer_align;
+  unsigned int rate;
+  snd_pcm_uframes_t start_threshold, stop_threshold;
+  snd_pcm_uframes_t period_size = 0;
+  snd_pcm_uframes_t chunk_size = 0;
+  int start_delay = 0;
+  int stop_delay = 0;
+  snd_pcm_state_t state;
+  snd_pcm_info_t *info;
+
+  period_size = tech_pvt-&gt;alsa_period_size;
+
+  snd_pcm_hw_params_alloca(&amp;params);
+  snd_pcm_sw_params_alloca(&amp;swparams);
+
+  if (stream == SND_PCM_STREAM_CAPTURE) {
+    err = snd_pcm_open(&amp;handle, tech_pvt-&gt;alsacname, stream, 0 | SND_PCM_NONBLOCK);
+  } else {
+    err = snd_pcm_open(&amp;handle, tech_pvt-&gt;alsapname, stream, 0 | SND_PCM_NONBLOCK);
+  }
+  if (err &lt; 0) {
+    ERRORA
+      (&quot;snd_pcm_open failed with error '%s' on device '%s', if you are using a plughw:n device please change it to be a default:n device (so to allow it to be shared with other concurrent programs), or maybe you are using an ALSA voicemodem and slmodemd&quot;
+       &quot; is running?\n&quot;, SKYPIAX_P_LOG, snd_strerror(err),
+       stream == SND_PCM_STREAM_CAPTURE ? tech_pvt-&gt;alsacname : tech_pvt-&gt;alsapname);
+    return NULL;
+  }
+
+  snd_pcm_info_alloca(&amp;info);
+
+  if ((err = snd_pcm_info(handle, info)) &lt; 0) {
+    ERRORA(&quot;info error: %s&quot;, SKYPIAX_P_LOG, snd_strerror(err));
+    return NULL;
+  }
+
+  err = snd_pcm_nonblock(handle, 1);
+  if (err &lt; 0) {
+    ERRORA(&quot;nonblock setting error: %s&quot;, SKYPIAX_P_LOG, snd_strerror(err));
+    return NULL;
+  }
+
+  err = snd_pcm_hw_params_any(handle, params);
+  if (err &lt; 0) {
+    ERRORA(&quot;Broken configuration for this PCM, no configurations available: %s\n&quot;,
+           SKYPIAX_P_LOG, snd_strerror(err));
+    return NULL;
+  }
+
+  err = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
+  if (err &lt; 0) {
+    ERRORA(&quot;Access type not available: %s\n&quot;, SKYPIAX_P_LOG, snd_strerror(err));
+    return NULL;
+  }
+  err = snd_pcm_hw_params_set_format(handle, params, celliax_format);
+  if (err &lt; 0) {
+    ERRORA(&quot;Sample format non available: %s\n&quot;, SKYPIAX_P_LOG, snd_strerror(err));
+    return NULL;
+  }
+  err = snd_pcm_hw_params_set_channels(handle, params, 1);
+  if (err &lt; 0) {
+    DEBUGA_SKYPE(&quot;Channels count set failed: %s\n&quot;, SKYPIAX_P_LOG, snd_strerror(err));
+  }
+#if 1
+  unsigned int chan_num;
+  err = snd_pcm_hw_params_get_channels(params, &amp;chan_num);
+  if (err &lt; 0) {
+    ERRORA(&quot;Channels count non available: %s\n&quot;, SKYPIAX_P_LOG, snd_strerror(err));
+    return NULL;
+  }
+  if (chan_num &lt; 1 || chan_num &gt; 2) {
+    ERRORA(&quot;Channels count MUST BE 1 or 2, it is: %d\n&quot;, SKYPIAX_P_LOG, chan_num);
+    ERRORA(&quot;Channels count MUST BE 1 or 2, it is: %d on %s %s\n&quot;, SKYPIAX_P_LOG, chan_num,
+           tech_pvt-&gt;alsapname, tech_pvt-&gt;alsacname);
+    return NULL;
+  } else {
+    if (chan_num == 1) {
+      if (stream == SND_PCM_STREAM_CAPTURE)
+        tech_pvt-&gt;alsa_capture_is_mono = 1;
+      else
+        tech_pvt-&gt;alsa_play_is_mono = 1;
+    } else {
+      if (stream == SND_PCM_STREAM_CAPTURE)
+        tech_pvt-&gt;alsa_capture_is_mono = 0;
+      else
+        tech_pvt-&gt;alsa_play_is_mono = 0;
+    }
+  }
+#else
+  tech_pvt-&gt;alsa_capture_is_mono = 1;
+  tech_pvt-&gt;alsa_play_is_mono = 1;
+#endif
+
+#if 0
+  unsigned int buffer_time = 0;
+  unsigned int period_time = 0;
+  snd_pcm_uframes_t period_frames = 0;
+  snd_pcm_uframes_t buffer_frames = 0;
+
+  if (buffer_time == 0 &amp;&amp; buffer_frames == 0) {
+    err = snd_pcm_hw_params_get_buffer_time_max(params, &amp;buffer_time, 0);
+    assert(err &gt;= 0);
+    if (buffer_time &gt; 500000)
+      buffer_time = 500000;
+  }
+  if (period_time == 0 &amp;&amp; period_frames == 0) {
+    if (buffer_time &gt; 0)
+      period_time = buffer_time / 4;
+    else
+      period_frames = buffer_frames / 4;
+  }
+  if (period_time &gt; 0)
+    err = snd_pcm_hw_params_set_period_time_near(handle, params, &amp;period_time, 0);
+  else
+    err = snd_pcm_hw_params_set_period_size_near(handle, params, &amp;period_frames, 0);
+  assert(err &gt;= 0);
+  if (buffer_time &gt; 0) {
+    err = snd_pcm_hw_params_set_buffer_time_near(handle, params, &amp;buffer_time, 0);
+  } else {
+    err = snd_pcm_hw_params_set_buffer_size_near(handle, params, &amp;buffer_frames);
+  }
+#endif
+
+#if 1
+  rate = tech_pvt-&gt;celliax_sound_rate;
+  err = snd_pcm_hw_params_set_rate_near(handle, params, &amp;rate, 0);
+  if ((float) tech_pvt-&gt;celliax_sound_rate * 1.05 &lt; rate
+      || (float) tech_pvt-&gt;celliax_sound_rate * 0.95 &gt; rate) {
+    WARNINGA(&quot;Rate is not accurate (requested = %iHz, got = %iHz)\n&quot;, SKYPIAX_P_LOG,
+             tech_pvt-&gt;celliax_sound_rate, rate);
+  }
+
+  if (err &lt; 0) {
+    ERRORA(&quot;Error setting rate: %s\n&quot;, SKYPIAX_P_LOG, snd_strerror(err));
+    return NULL;
+  }
+  tech_pvt-&gt;celliax_sound_rate = rate;
+
+  err = snd_pcm_hw_params_set_period_size_near(handle, params, &amp;period_size, 0);
+
+  if (err &lt; 0) {
+    ERRORA(&quot;Error setting period_size: %s\n&quot;, SKYPIAX_P_LOG, snd_strerror(err));
+    return NULL;
+  }
+
+  tech_pvt-&gt;alsa_period_size = period_size;
+
+  tech_pvt-&gt;alsa_buffer_size = tech_pvt-&gt;alsa_period_size * tech_pvt-&gt;alsa_periods_in_buffer;
+
+  err = snd_pcm_hw_params_set_buffer_size_near(handle, params, &amp;tech_pvt-&gt;alsa_buffer_size);
+
+  if (err &lt; 0) {
+    ERRORA(&quot;Error setting buffer_size: %s\n&quot;, SKYPIAX_P_LOG, snd_strerror(err));
+    return NULL;
+  }
+#endif
+
+  err = snd_pcm_hw_params(handle, params);
+  if (err &lt; 0) {
+    ERRORA(&quot;Unable to install hw params: %s\n&quot;, SKYPIAX_P_LOG, snd_strerror(err));
+    return NULL;
+  }
+
+  snd_pcm_hw_params_get_period_size(params, &amp;chunk_size, 0);
+  snd_pcm_hw_params_get_buffer_size(params, &amp;buffer_size);
+  if (chunk_size == buffer_size) {
+    ERRORA(&quot;Can't use period equal to buffer size (%lu == %lu)\n&quot;, SKYPIAX_P_LOG,
+           chunk_size, buffer_size);
+    return NULL;
+  }
+
+  snd_pcm_sw_params_current(handle, swparams);
+
+#if 0
+  err = snd_pcm_sw_params_get_xfer_align(swparams, &amp;xfer_align);
+  if (err &lt; 0) {
+    ERRORA(&quot;Unable to obtain xfer align: %s\n&quot;, SKYPIAX_P_LOG, snd_strerror(err));
+  }
+  NOTICA(&quot;xfer_align: %d\n&quot;, SKYPIAX_P_LOG, xfer_align);
+  /* for some reason, on some platforms, xfer_align here is zero, that gives a floating point exception later. So, let's try to force it to 160, the frame size used by celliax */
+  xfer_align = tech_pvt-&gt;alsa_period_size;
+  NOTICA(&quot;xfer_align: %d\n&quot;, SKYPIAX_P_LOG, xfer_align);
+
+  err = snd_pcm_sw_params_set_xfer_align(handle, swparams, xfer_align);
+  if (err &lt; 0) {
+    ERRORA(&quot;Error setting xfer_align: %s\n&quot;, SKYPIAX_P_LOG, snd_strerror(err));
+  }
+  NOTICA(&quot;xfer_align: %d\n&quot;, SKYPIAX_P_LOG, xfer_align);
+
+  err = snd_pcm_sw_params_get_xfer_align(swparams, &amp;xfer_align);
+  if (err &lt; 0) {
+    ERRORA(&quot;Unable to obtain xfer align: %s\n&quot;, SKYPIAX_P_LOG, snd_strerror(err));
+  }
+  NOTICA(&quot;xfer_align: %d\n&quot;, SKYPIAX_P_LOG, xfer_align);
+#endif
+
+  /*
+     if (sleep_min)
+     xfer_align = 1;
+     err = snd_pcm_sw_params_set_sleep_min(handle, swparams,
+     0);
+
+     if (err &lt; 0) {
+     ERRORA(&quot;Error setting slep_min: %s\n&quot;, SKYPIAX_P_LOG, snd_strerror(err));
+     }
+   */
+  n = chunk_size;
+  err = snd_pcm_sw_params_set_avail_min(handle, swparams, n);
+  if (err &lt; 0) {
+    ERRORA(&quot;Error setting avail_min: %s\n&quot;, SKYPIAX_P_LOG, snd_strerror(err));
+  }
+#if 0
+  /* round up to closest transfer boundary */
+  if (xfer_align == 0) {        //so to avoid floating point exception ????
+    xfer_align = 160;
+  }
+  //original n = (buffer_size / xfer_align) * xfer_align;
+  n = (chunk_size / xfer_align) * xfer_align;
+#endif
+  if (stream == SND_PCM_STREAM_CAPTURE) {
+    start_delay = 1;
+  }
+  if (start_delay &lt;= 0) {
+    start_threshold = n + (double) rate *start_delay / 1000000;
+  } else {
+    start_threshold = (double) rate *start_delay / 1000000;
+  }
+  if (start_threshold &lt; 1)
+    start_threshold = 1;
+  if (start_threshold &gt; n)
+    start_threshold = n;
+  err = snd_pcm_sw_params_set_start_threshold(handle, swparams, start_threshold);
+  if (err &lt; 0) {
+    ERRORA(&quot;Error setting start_threshold: %s\n&quot;, SKYPIAX_P_LOG, snd_strerror(err));
+  }
+
+  if (stop_delay &lt;= 0)
+    stop_threshold = buffer_size + (double) rate *stop_delay / 1000000;
+  else
+    stop_threshold = (double) rate *stop_delay / 1000000;
+
+  if (stream == SND_PCM_STREAM_CAPTURE) {
+    stop_threshold = -1;
+  }
+
+  err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, stop_threshold);
+
+  if (err &lt; 0) {
+    ERRORA(&quot;Error setting stop_threshold: %s\n&quot;, SKYPIAX_P_LOG, snd_strerror(err));
+  }
+#if 0
+  err = snd_pcm_sw_params_set_xfer_align(handle, swparams, xfer_align);
+
+  if (err &lt; 0) {
+    ERRORA(&quot;Error setting xfer_align: %s\n&quot;, SKYPIAX_P_LOG, snd_strerror(err));
+  }
+#endif
+
+  if (snd_pcm_sw_params(handle, swparams) &lt; 0) {
+    ERRORA(&quot;Error installing software parameters: %s\n&quot;, SKYPIAX_P_LOG,
+           snd_strerror(err));
+  }
+
+  err = snd_pcm_poll_descriptors_count(handle);
+  if (err &lt;= 0) {
+    ERRORA(&quot;Unable to get a poll descriptors count, error is %s\n&quot;, SKYPIAX_P_LOG,
+           snd_strerror(err));
+    return NULL;
+  }
+
+  if (err != 1) {               //number of poll descriptors
+    DEBUGA_SKYPE(&quot;Can't handle more than one device\n&quot;, SKYPIAX_P_LOG);
+    return NULL;
+  }
+
+  err = snd_pcm_poll_descriptors(handle, &amp;tech_pvt-&gt;pfd, err);
+  if (err != 1) {
+    ERRORA(&quot;snd_pcm_poll_descriptors failed, %s\n&quot;, SKYPIAX_P_LOG, snd_strerror(err));
+    return NULL;
+  }
+  DEBUGA_SKYPE(&quot;Acquired fd %d from the poll descriptor\n&quot;, SKYPIAX_P_LOG, tech_pvt-&gt;pfd.fd);
+
+  if (stream == SND_PCM_STREAM_CAPTURE) {
+    tech_pvt-&gt;celliax_sound_capt_fd = tech_pvt-&gt;pfd.fd;
+  }
+
+  state = snd_pcm_state(handle);
+
+  if (state != SND_PCM_STATE_RUNNING) {
+    if (state != SND_PCM_STATE_PREPARED) {
+      err = snd_pcm_prepare(handle);
+      if (err) {
+        ERRORA(&quot;snd_pcm_prepare failed, %s\n&quot;, SKYPIAX_P_LOG, snd_strerror(err));
+        return NULL;
+      }
+      DEBUGA_SKYPE(&quot;prepared!\n&quot;, SKYPIAX_P_LOG);
+    }
+    if (stream == SND_PCM_STREAM_CAPTURE) {
+      err = snd_pcm_start(handle);
+      if (err) {
+        ERRORA(&quot;snd_pcm_start failed, %s\n&quot;, SKYPIAX_P_LOG, snd_strerror(err));
+        return NULL;
+      }
+      DEBUGA_SKYPE(&quot;started!\n&quot;, SKYPIAX_P_LOG);
+    }
+  }
+  if (option_debug &gt; 1) {
+    snd_output_t *output = NULL;
+    err = snd_output_stdio_attach(&amp;output, stdout, 0);
+    if (err &lt; 0) {
+      ERRORA(&quot;snd_output_stdio_attach failed: %s\n&quot;, SKYPIAX_P_LOG, snd_strerror(err));
+    }
+    snd_pcm_dump(handle, output);
+  }
+  if (option_debug &gt; 1)
+    DEBUGA_SKYPE(&quot;ALSA handle = %ld\n&quot;, SKYPIAX_P_LOG, (long int) handle);
+  return handle;
+
+}
+
+#ifdef NOTDEF
+/*! \brief Read audio frames from interface */
+
+struct ast_frame *alsa_read(private_t * tech_pvt)
+{
+  static struct ast_frame f;
+  static short __buf[SKYPIAX_FRAME_SIZE + AST_FRIENDLY_OFFSET / 2];
+  static short __buf2[(SKYPIAX_FRAME_SIZE + AST_FRIENDLY_OFFSET / 2) * 2];
+  short *buf;
+  short *buf2;
+  static int readpos = 0;
+  static int left = SKYPIAX_FRAME_SIZE;
+  snd_pcm_state_t state;
+  int r = 0;
+  int off = 0;
+  int error = 0;
+  //time_t now_timestamp;
+
+  //memset(&amp;f, 0, sizeof(struct ast_frame)); //giova
+
+  f.frametype = AST_FRAME_NULL;
+  f.subclass = 0;
+  f.samples = 0;
+  f.datalen = 0;
+  f.data = NULL;
+  f.offset = 0;
+  f.src = celliax_type;
+  f.mallocd = 0;
+  f.delivery.tv_sec = 0;
+  f.delivery.tv_usec = 0;
+
+  state = snd_pcm_state(tech_pvt-&gt;alsac);
+  if (state != SND_PCM_STATE_RUNNING) {
+    DEBUGA_SKYPE(&quot;ALSA read state is not SND_PCM_STATE_RUNNING\n&quot;, SKYPIAX_P_LOG);
+
+    if (state != SND_PCM_STATE_PREPARED) {
+      error = snd_pcm_prepare(tech_pvt-&gt;alsac);
+      if (error) {
+        ERRORA(&quot;snd_pcm_prepare failed, %s\n&quot;, SKYPIAX_P_LOG, snd_strerror(error));
+        return &amp;f;
+      }
+      DEBUGA_SKYPE(&quot;prepared!\n&quot;, SKYPIAX_P_LOG);
+    }
+    usleep(1000);
+    error = snd_pcm_start(tech_pvt-&gt;alsac);
+    if (error) {
+      ERRORA(&quot;snd_pcm_start failed, %s\n&quot;, SKYPIAX_P_LOG, snd_strerror(error));
+      return &amp;f;
+    }
+    DEBUGA_SKYPE(&quot;started!\n&quot;, SKYPIAX_P_LOG);
+    usleep(1000);
+  }
+
+  buf = __buf + AST_FRIENDLY_OFFSET / 2;
+  buf2 = __buf2 + ((AST_FRIENDLY_OFFSET / 2) * 2);
+
+  if (tech_pvt-&gt;alsa_capture_is_mono) {
+    r = snd_pcm_readi(tech_pvt-&gt;alsac, buf + readpos, left);
+  } else {
+    r = snd_pcm_readi(tech_pvt-&gt;alsac, buf2 + (readpos * 2), left);
+
+    int a = 0;
+    int i = 0;
+    for (i = 0; i &lt; (SKYPIAX_FRAME_SIZE + AST_FRIENDLY_OFFSET / 2) * 2;) {
+      __buf[a] = (__buf2[i] + __buf2[i + 1]) / 2;   //comment out this line to use only left
+      //__buf[a] = __buf2[i]; // enable this line to use only left
+      a++;
+      i++;
+      i++;
+    }
+  }
+
+  if (r == -EPIPE) {
+    ERRORA(&quot;XRUN read\n\n\n\n\n&quot;, SKYPIAX_P_LOG);
+    return &amp;f;
+  } else if (r == -ESTRPIPE) {
+    ERRORA(&quot;-ESTRPIPE\n&quot;, SKYPIAX_P_LOG);
+    return &amp;f;
+
+  } else if (r == -EAGAIN) {
+    DEBUGA_SKYPE(&quot;ALSA read -EAGAIN, the soundcard is not ready to be read by celliax\n&quot;,
+                 SKYPIAX_P_LOG);
+    while (r == -EAGAIN) {
+      usleep(1000);
+
+      if (tech_pvt-&gt;alsa_capture_is_mono) {
+        r = snd_pcm_readi(tech_pvt-&gt;alsac, buf + readpos, left);
+      } else {
+        r = snd_pcm_readi(tech_pvt-&gt;alsac, buf2 + (readpos * 2), left);
+
+        int a = 0;
+        int i = 0;
+        for (i = 0; i &lt; (SKYPIAX_FRAME_SIZE + AST_FRIENDLY_OFFSET / 2) * 2;) {
+          __buf[a] = (__buf2[i] + __buf2[i + 1]) / 2;
+          a++;
+          i++;
+          i++;
+        }
+      }
+
+    }
+  } else if (r &lt; 0) {
+    WARNINGA(&quot;ALSA Read error: %s\n&quot;, SKYPIAX_P_LOG, snd_strerror(r));
+  } else if (r &gt;= 0) {
+    //DEBUGA_SKYPE(&quot;read: r=%d, readpos=%d, left=%d, off=%d\n&quot;, SKYPIAX_P_LOG, r, readpos, left, off);
+    off -= r;                   //what is the meaning of this? a leftover, probably
+  }
+  /* Update positions */
+  readpos += r;
+  left -= r;
+
+  if (readpos &gt;= SKYPIAX_FRAME_SIZE) {
+    /* A real frame */
+    readpos = 0;
+    left = SKYPIAX_FRAME_SIZE;
+
+    f.frametype = AST_FRAME_VOICE;
+    f.subclass = AST_FORMAT_SLINEAR;
+    f.samples = SKYPIAX_FRAME_SIZE;
+    f.datalen = SKYPIAX_FRAME_SIZE * 2;
+    f.data = buf;
+    f.offset = AST_FRIENDLY_OFFSET;
+    f.src = celliax_type;
+    f.mallocd = 0;
+#ifdef ALSA_MONITOR
+    alsa_monitor_read((char *) buf, SKYPIAX_FRAME_SIZE * 2);
+#endif
+
+  }
+  return &amp;f;
+}
+
+/*! \brief Write audio frames to interface */
+int alsa_write(private_t * tech_pvt, struct ast_frame *f)
+{
+  static char sizbuf[8000];
+  static char sizbuf2[16000];
+  static char silencebuf[8000];
+  static int sizpos = 0;
+  int len = sizpos;
+  int pos;
+  int res = 0;
+  time_t now_timestamp;
+  /* size_t frames = 0; */
+  snd_pcm_state_t state;
+  snd_pcm_sframes_t delayp1;
+  snd_pcm_sframes_t delayp2;
+
+  /* We have to digest the frame in 160-byte portions */
+  if (f-&gt;datalen &gt; sizeof(sizbuf) - sizpos) {
+    ERRORA(&quot;Frame too large\n&quot;, SKYPIAX_P_LOG);
+    res = -1;
+  } else {
+    memcpy(sizbuf + sizpos, f-&gt;data, f-&gt;datalen);
+    len += f-&gt;datalen;
+    pos = 0;
+#ifdef ALSA_MONITOR
+    alsa_monitor_write(sizbuf, len);
+#endif
+    state = snd_pcm_state(tech_pvt-&gt;alsap);
+    if (state == SND_PCM_STATE_XRUN) {
+      int i;
+
+      DEBUGA_SKYPE
+        (&quot;You've got an ALSA write XRUN in the past (celliax can't fill the soundcard buffer fast enough). If this happens often (not after silence or after a pause in the speech, that's OK), and appear to damage the sound quality, first check if you have some IRQ problem, maybe sharing the soundcard IRQ with a broken or heavy loaded ethernet or graphic card. Then consider to increase the alsa_periods_in_buffer (now is set to %d) for this interface in the config file\n&quot;,
+         SKYPIAX_P_LOG, tech_pvt-&gt;alsa_periods_in_buffer);
+      res = snd_pcm_prepare(tech_pvt-&gt;alsap);
+      if (res) {
+        ERRORA(&quot;audio play prepare failed: %s\n&quot;, SKYPIAX_P_LOG, snd_strerror(res));
+      } else {
+        res = snd_pcm_format_set_silence(celliax_format, silencebuf, len / 2);
+        if (res &lt; 0) {
+          DEBUGA_SKYPE(&quot;Silence error %s\n&quot;, SKYPIAX_P_LOG, snd_strerror(res));
+          res = -1;
+        }
+        for (i = 0; i &lt; (tech_pvt-&gt;alsa_periods_in_buffer - 1); i++) {
+          res = snd_pcm_writei(tech_pvt-&gt;alsap, silencebuf, len / 2);
+          if (res != len / 2) {
+            DEBUGA_SKYPE(&quot;Write returned a different quantity: %d\n&quot;, SKYPIAX_P_LOG, res);
+            res = -1;
+          } else if (res &lt; 0) {
+            DEBUGA_SKYPE(&quot;Write error %s\n&quot;, SKYPIAX_P_LOG, snd_strerror(res));
+            res = -1;
+          }
+        }
+      }
+
+    }
+
+    res = snd_pcm_delay(tech_pvt-&gt;alsap, &amp;delayp1);
+    if (res &lt; 0) {
+      DEBUGA_SKYPE(&quot;Error %d on snd_pcm_delay: \&quot;%s\&quot;\n&quot;, SKYPIAX_P_LOG, res,
+                   snd_strerror(res));
+      res = snd_pcm_prepare(tech_pvt-&gt;alsap);
+      if (res) {
+        DEBUGA_SKYPE(&quot;snd_pcm_prepare failed: '%s'\n&quot;, SKYPIAX_P_LOG, snd_strerror(res));
+      }
+      res = snd_pcm_delay(tech_pvt-&gt;alsap, &amp;delayp1);
+    }
+
+    delayp2 = snd_pcm_avail_update(tech_pvt-&gt;alsap);
+    if (delayp2 &lt; 0) {
+      DEBUGA_SKYPE(&quot;Error %d on snd_pcm_avail_update: \&quot;%s\&quot;\n&quot;, SKYPIAX_P_LOG,
+                   (int) delayp2, snd_strerror(delayp2));
+
+      res = snd_pcm_prepare(tech_pvt-&gt;alsap);
+      if (res) {
+        DEBUGA_SKYPE(&quot;snd_pcm_prepare failed: '%s'\n&quot;, SKYPIAX_P_LOG, snd_strerror(res));
+      }
+      delayp2 = snd_pcm_avail_update(tech_pvt-&gt;alsap);
+    }
+
+    if (                        /* delayp1 != 0 &amp;&amp; delayp1 != 160 */
+         delayp1 &lt; 160 || delayp2 &gt; tech_pvt-&gt;alsa_buffer_size) {
+
+      res = snd_pcm_prepare(tech_pvt-&gt;alsap);
+      if (res) {
+        DEBUGA_SKYPE
+          (&quot;snd_pcm_prepare failed while trying to prevent an ALSA write XRUN: %s, delayp1=%d, delayp2=%d\n&quot;,
+           SKYPIAX_P_LOG, snd_strerror(res), (int) delayp1, (int) delayp2);
+      } else {
+
+        int i;
+        for (i = 0; i &lt; (tech_pvt-&gt;alsa_periods_in_buffer - 1); i++) {
+          res = snd_pcm_format_set_silence(celliax_format, silencebuf, len / 2);
+          if (res &lt; 0) {
+            DEBUGA_SKYPE(&quot;Silence error %s\n&quot;, SKYPIAX_P_LOG, snd_strerror(res));
+            res = -1;
+          }
+          res = snd_pcm_writei(tech_pvt-&gt;alsap, silencebuf, len / 2);
+          if (res &lt; 0) {
+            DEBUGA_SKYPE(&quot;Write error %s\n&quot;, SKYPIAX_P_LOG, snd_strerror(res));
+            res = -1;
+          } else if (res != len / 2) {
+            DEBUGA_SKYPE(&quot;Write returned a different quantity: %d\n&quot;, SKYPIAX_P_LOG, res);
+            res = -1;
+          }
+        }
+
+        DEBUGA_SKYPE
+          (&quot;PREVENTING an ALSA write XRUN (celliax can't fill the soundcard buffer fast enough). If this happens often (not after silence or after a pause in the speech, that's OK), and appear to damage the sound quality, first check if you have some IRQ problem, maybe sharing the soundcard IRQ with a broken or heavy loaded ethernet or graphic card. Then consider to increase the alsa_periods_in_buffer (now is set to %d) for this interface in the config file. delayp1=%d, delayp2=%d\n&quot;,
+           SKYPIAX_P_LOG, tech_pvt-&gt;alsa_periods_in_buffer, (int) delayp1, (int) delayp2);
+      }
+
+    }
+
+    memset(sizbuf2, 0, sizeof(sizbuf2));
+    if (tech_pvt-&gt;alsa_play_is_mono) {
+      res = snd_pcm_writei(tech_pvt-&gt;alsap, sizbuf, len / 2);
+    } else {
+      int a = 0;
+      int i = 0;
+      for (i = 0; i &lt; 8000;) {
+        sizbuf2[a] = sizbuf[i];
+        a++;
+        i++;
+        sizbuf2[a] = sizbuf[i];
+        a++;
+        i--;
+        sizbuf2[a] = sizbuf[i]; // comment out this line to use only left 
+        a++;
+        i++;
+        sizbuf2[a] = sizbuf[i]; // comment out this line to use only left
+        a++;
+        i++;
+      }
+      res = snd_pcm_writei(tech_pvt-&gt;alsap, sizbuf2, len);
+    }
+    if (res == -EPIPE) {
+      DEBUGA_SKYPE
+        (&quot;ALSA write EPIPE (XRUN) (celliax can't fill the soundcard buffer fast enough). If this happens often (not after silence or after a pause in the speech, that's OK), and appear to damage the sound quality, first check if you have some IRQ problem, maybe sharing the soundcard IRQ with a broken or heavy loaded ethernet or graphic card. Then consider to increase the alsa_periods_in_buffer (now is set to %d) for this interface in the config file. delayp1=%d, delayp2=%d\n&quot;,
+         SKYPIAX_P_LOG, tech_pvt-&gt;alsa_periods_in_buffer, (int) delayp1, (int) delayp2);
+      res = snd_pcm_prepare(tech_pvt-&gt;alsap);
+      if (res) {
+        ERRORA(&quot;audio play prepare failed: %s\n&quot;, SKYPIAX_P_LOG, snd_strerror(res));
+      } else {
+
+        if (tech_pvt-&gt;alsa_play_is_mono) {
+          res = snd_pcm_writei(tech_pvt-&gt;alsap, sizbuf, len / 2);
+        } else {
+          int a = 0;
+          int i = 0;
+          for (i = 0; i &lt; 8000;) {
+            sizbuf2[a] = sizbuf[i];
+            a++;
+            i++;
+            sizbuf2[a] = sizbuf[i];
+            a++;
+            i--;
+            sizbuf2[a] = sizbuf[i];
+            a++;
+            i++;
+            sizbuf2[a] = sizbuf[i];
+            a++;
+            i++;
+          }
+          res = snd_pcm_writei(tech_pvt-&gt;alsap, sizbuf2, len);
+        }
+
+      }
+
+    } else {
+      if (res == -ESTRPIPE) {
+        ERRORA(&quot;You've got some big problems\n&quot;, SKYPIAX_P_LOG);
+      } else if (res == -EAGAIN) {
+        res = 0;
+      } else if (res &lt; 0) {
+        ERRORA(&quot;Error %d on audio write: \&quot;%s\&quot;\n&quot;, SKYPIAX_P_LOG, res,
+               snd_strerror(res));
+      }
+    }
+  }
+
+  if (tech_pvt-&gt;audio_play_reset_period) {
+    time(&amp;now_timestamp);
+    if ((now_timestamp - tech_pvt-&gt;audio_play_reset_timestamp) &gt; tech_pvt-&gt;audio_play_reset_period) {
+      if (option_debug)
+        DEBUGA_SKYPE(&quot;reset audio play\n&quot;, SKYPIAX_P_LOG);
+      res = snd_pcm_wait(tech_pvt-&gt;alsap, 1000);
+      if (res &lt; 0) {
+        ERRORA(&quot;audio play wait failed: %s\n&quot;, SKYPIAX_P_LOG, snd_strerror(res));
+      }
+      res = snd_pcm_drop(tech_pvt-&gt;alsap);
+      if (res) {
+        ERRORA(&quot;audio play drop failed: %s\n&quot;, SKYPIAX_P_LOG, snd_strerror(res));
+      }
+      res = snd_pcm_prepare(tech_pvt-&gt;alsap);
+      if (res) {
+        ERRORA(&quot;audio play prepare failed: %s\n&quot;, SKYPIAX_P_LOG, snd_strerror(res));
+      }
+      res = snd_pcm_wait(tech_pvt-&gt;alsap, 1000);
+      if (res &lt; 0) {
+        ERRORA(&quot;audio play wait failed: %s\n&quot;, SKYPIAX_P_LOG, snd_strerror(res));
+      }
+      time(&amp;tech_pvt-&gt;audio_play_reset_timestamp);
+    }
+  }
+  res = 0;
+  if (res &gt; 0)
+    res = 0;
+  return res;
+}
+
+#endif //NOTDEF
+
+/*! \brief Write audio frames to interface */
+#endif /* SKYPIAX_ALSA */
+
+int celliax_call(private_t * tech_pvt, char *rdest, int timeout)
+{
+        char msg_to_skype[1024];
+
+        //celliax_sleep(5000);
+        DEBUGA_SKYPE(&quot;Calling Skype, rdest is: %s\n&quot;, SKYPIAX_P_LOG, rdest);
+        //celliax_signaling_write(tech_pvt, &quot;SET AGC OFF&quot;);
+        //celliax_sleep(10000);
+        //celliax_signaling_write(tech_pvt, &quot;SET AEC OFF&quot;);
+        //celliax_sleep(10000);
+
+        sprintf(msg_to_skype, &quot;CALL %s&quot;, rdest);
+        //if (celliax_signaling_write(tech_pvt, msg_to_skype) &lt; 0) {
+                //ERRORA(&quot;failed to communicate with Skype client, now exit\n&quot;, SKYPIAX_P_LOG);
+                //return -1;
+        //}
+        return 0;
+}
+
+
+int celliax_senddigit(private_t * tech_pvt, char digit)
+{
+        char msg_to_skype[1024];
+
+        DEBUGA_SKYPE(&quot;DIGIT received: %c\n&quot;, SKYPIAX_P_LOG, digit);
+        sprintf(msg_to_skype, &quot;SET CALL %s DTMF %c&quot;, tech_pvt-&gt;skype_call_id, digit);
+        //celliax_signaling_write(tech_pvt, msg_to_skype);
+
+        return 0;
+}
+
</ins></span></pre></div>
<a id="freeswitchbranchesgmaruzzmod_celliaxmod_celliaxc"></a>
<div class="modfile"><h4>Modified: freeswitch/branches/gmaruzz/mod_celliax/mod_celliax.c (14633 => 14634)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/branches/gmaruzz/mod_celliax/mod_celliax.c        2009-08-25 11:51:55 UTC (rev 14633)
+++ freeswitch/branches/gmaruzz/mod_celliax/mod_celliax.c        2009-08-25 18:58:31 UTC (rev 14634)
</span><span class="lines">@@ -1347,24 +1347,17 @@
</span><span class="cx">   globals.SKYPIAX_INTERFACES[interface_id].at_has_clcc = 0;
</span><span class="cx">   globals.SKYPIAX_INTERFACES[interface_id].at_has_ecam = 0;
</span><span class="cx"> 
</span><del>-#ifdef NOTDEF
-  .celliax_dir_entry_extension_prefix = 5;
</del><ins>+  globals.SKYPIAX_INTERFACES[interface_id].alsa_period_size = 160;
+  globals.SKYPIAX_INTERFACES[interface_id].alsa_periods_in_buffer = 4;
+  globals.SKYPIAX_INTERFACES[interface_id].celliax_sound_rate = 8000;
</ins><span class="cx"> 
</span><del>-#ifdef CELLIAX_ALSA
-  .alsa_period_size = 160,
-  .alsa_periods_in_buffer = 4,
-  .alsac = NULL,
-  .alsap = NULL,
-  .alsawrite_filled = 0,
-#endif /* CELLIAX_ALSA */
</del><ins>+  switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].alsacname , &quot;plughw:0&quot;);
+  switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].alsapname , &quot;plughw:0&quot;);
</ins><span class="cx"> 
</span><del>-#endif// NOTDEF
</del><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-
-
</del><span class="cx"> /*********************/
</span><span class="cx">                                 DEBUGA_SKYPE
</span><span class="cx">                                         (&quot;interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].X11_display=%s\n&quot;,
</span><span class="lines">@@ -1429,6 +1422,15 @@
</span><span class="cx"> 
</span><span class="cx">                                 switch_sleep(100000);
</span><span class="cx"> 
</span><ins>+                                  res = alsa_init(&amp;globals.SKYPIAX_INTERFACES[interface_id]);
+                                  if (res == -1) {
+                                          ERRORA(&quot;Failed initializing sound device\n&quot;, SKYPIAX_P_LOG);
+                                          /* we failed, free the PVT */
+                                          //if (tmp)
+                                                  //free(tmp);
+                                          //return NULL;
+                                  }
+
</ins><span class="cx"> #ifdef NOTDEF 
</span><span class="cx">                                 switch_threadattr_create(&amp;celliax_signaling_thread_attr, celliax_module_pool);
</span><span class="cx">                                 switch_threadattr_stacksize_set(celliax_signaling_thread_attr, SWITCH_THREAD_STACKSIZE);
</span><span class="lines">@@ -1628,6 +1630,7 @@
</span><span class="cx">         return SWITCH_STATUS_SUCCESS;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#ifdef NOTDEF
</ins><span class="cx"> void *SWITCH_THREAD_FUNC celliax_do_tcp_srv_thread(switch_thread_t * thread, void *obj)
</span><span class="cx"> {
</span><span class="cx">         return celliax_do_tcp_srv_thread_func(obj);
</span><span class="lines">@@ -1637,6 +1640,7 @@
</span><span class="cx"> {
</span><span class="cx">         return celliax_do_tcp_cli_thread_func(obj);
</span><span class="cx"> }
</span><ins>+#endif// NOTDEF
</ins><span class="cx"> 
</span><span class="cx"> void *SWITCH_THREAD_FUNC celliax_do_skypeapi_thread(switch_thread_t * thread, void *obj)
</span><span class="cx"> {
</span><span class="lines">@@ -1674,6 +1678,7 @@
</span><span class="cx">         return 0;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#ifdef NOTDEF
</ins><span class="cx"> int start_audio_threads(private_t * tech_pvt)
</span><span class="cx"> {
</span><span class="cx">         switch_threadattr_t *thd_attr = NULL;
</span><span class="lines">@@ -1706,6 +1711,7 @@
</span><span class="cx"> 
</span><span class="cx">         return 0;
</span><span class="cx"> }
</span><ins>+#endif// NOTDEF
</ins><span class="cx"> 
</span><span class="cx"> int new_inbound_channel(private_t * tech_pvt)
</span><span class="cx"> {
</span><span class="lines">@@ -1996,10 +2002,12 @@
</span><span class="cx"> /* END: Changes heres */
</span><span class="cx"> 
</span><span class="cx">         } else {
</span><ins>+#ifdef NOTDEF
</ins><span class="cx">                 if (globals.sk_console)
</span><span class="cx">                         celliax_signaling_write(globals.sk_console, (char *) cmd);
</span><span class="cx">                 else
</span><span class="cx">                         stream-&gt;write_function(stream, &quot;sk console is NOT yet assigned\n&quot;);
</span><ins>+#endif //NOTDEF
</ins><span class="cx">         }
</span><span class="cx">   end:
</span><span class="cx">         switch_safe_free(mycmd);
</span><span class="lines">@@ -2048,7 +2056,7 @@
</span><span class="cx"> 
</span><span class="cx">                         return SWITCH_STATUS_SUCCESS;
</span><span class="cx">                 } else {
</span><del>-                        celliax_signaling_write(tech_pvt, (char *) &amp;cmd[strlen(argv[0]) + 1]);
</del><ins>+                        //celliax_signaling_write(tech_pvt, (char *) &amp;cmd[strlen(argv[0]) + 1]);
</ins><span class="cx">                 }
</span><span class="cx">         } else {
</span><span class="cx">                 stream-&gt;write_function(stream, &quot;ERROR, usage: %s&quot;, SKYPIAX_SYNTAX);
</span><span class="lines">@@ -2235,7 +2243,7 @@
</span><span class="cx">                         //available_celliax_interface-&gt;ib_calls++;
</span><span class="cx"> 
</span><span class="cx">                         sprintf(msg_to_skype, &quot;ALTER CALL %s TRANSFER %s&quot;, id, available_celliax_interface-&gt;skype_user);
</span><del>-                        celliax_signaling_write(tech_pvt, msg_to_skype);
</del><ins>+                        //celliax_signaling_write(tech_pvt, msg_to_skype);
</ins><span class="cx">                         if (tech_pvt-&gt;interface_state == SKYPIAX_STATE_SELECTED) {
</span><span class="cx">                                 tech_pvt-&gt;interface_state = SKYPIAX_STATE_IDLE;        //we marked it SKYPIAX_STATE_SELECTED just in case it has to make an outbound call
</span><span class="cx">                         }
</span><span class="lines">@@ -2245,7 +2253,7 @@
</span><span class="cx">                                 (&quot;Not answering the skype_call %s, because we are already in a celliax call(%s) and not transferring, because no other celliax interfaces are available\n&quot;,
</span><span class="cx">                                  SKYPIAX_P_LOG, id, tech_pvt-&gt;skype_call_id);
</span><span class="cx">                         sprintf(msg_to_skype, &quot;ALTER CALL %s END HANGUP&quot;, id);
</span><del>-                        celliax_signaling_write(tech_pvt, msg_to_skype);
</del><ins>+                        //celliax_signaling_write(tech_pvt, msg_to_skype);
</ins><span class="cx">                 }
</span><span class="cx">                 switch_sleep(10000);
</span><span class="cx">                 DEBUGA_SKYPE
</span></span></pre>
</div>
</div>
<div id="footer">See you at ClueCon</div>

</body>
</html>