<!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="$(shell svnversion -n .)"'
</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 <switch.h>
</span><span class="cx"> #include <switch_version.h>
</span><span class="cx"> #include <termios.h>
</span><span class="cx"> #include <sys/ioctl.h>
</span><span class="cx"> #include <iconv.h>
</span><ins>+#ifdef CELLIAX_ALSA
+#define ALSA_PCM_NEW_HW_PARAMS_API
+#define ALSA_PCM_NEW_SW_PARAMS_API
+#include <alsa/asoundlib.h>
+#endif /* CELLIAX_ALSA */
</ins><span class="cx">
</span><ins>+
</ins><span class="cx"> #ifndef WIN32
</span><span class="cx"> #include <sys/time.h>
</span><span class="cx"> #include <X11/Xlib.h>
</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; /*!< \brief handle of the ALSA capture audio device */
+ snd_pcm_t *alsap; /*!< \brief handle of the ALSA playback audio device */
+ char alsacname[50]; /*!< \brief name of the ALSA capture audio device */
+ char alsapname[50]; /*!< \brief name of the ALSA playback audio device */
+ int alsa_period_size; /*!< \brief ALSA period_size, in byte */
+ int alsa_periods_in_buffer; /*!< \brief how many periods in ALSA buffer, to calculate buffer_size */
+ unsigned long int alsa_buffer_size; /*!< \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) && !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("DIGIT received: %c\n", SKYPIAX_P_LOG, digit);
-        sprintf(msg_to_skype, "SET CALL %s DTMF %c", tech_pvt->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("Calling Skype, rdest is: %s\n", SKYPIAX_P_LOG, rdest);
-        //celliax_signaling_write(tech_pvt, "SET AGC OFF");
-        //celliax_sleep(10000);
-        //celliax_signaling_write(tech_pvt, "SET AEC OFF");
-        //celliax_sleep(10000);
-
-        sprintf(msg_to_skype, "CALL %s", rdest);
-        if (celliax_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;
-}
-
</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->alsac = alsa_open_dev(tech_pvt, SND_PCM_STREAM_CAPTURE);
+ if (!tech_pvt->alsac) {
+ ERRORA("Failed opening ALSA capture device: %s\n", SKYPIAX_P_LOG, tech_pvt->alsacname);
+ if (alsa_shutdown(tech_pvt)) {
+ ERRORA("alsa_shutdown failed\n", SKYPIAX_P_LOG);
+ return -1;
+ }
+ return -1;
+ }
+ tech_pvt->alsap = alsa_open_dev(tech_pvt, SND_PCM_STREAM_PLAYBACK);
+ if (!tech_pvt->alsap) {
+ ERRORA("Failed opening ALSA playback device: %s\n", SKYPIAX_P_LOG, tech_pvt->alsapname);
+ if (alsa_shutdown(tech_pvt)) {
+ ERRORA("alsa_shutdown failed\n", 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->alsap) {
+ err = snd_pcm_drop(tech_pvt->alsap);
+ if (err < 0) {
+ ERRORA("device [%s], snd_pcm_drop failed with error '%s'\n", SKYPIAX_P_LOG,
+ tech_pvt->alsapname, snd_strerror(err));
+ return -1;
+ }
+ err = snd_pcm_close(tech_pvt->alsap);
+ if (err < 0) {
+ ERRORA("device [%s], snd_pcm_close failed with error '%s'\n", SKYPIAX_P_LOG,
+ tech_pvt->alsapname, snd_strerror(err));
+ return -1;
+ }
+ }
+ if (tech_pvt->alsac) {
+ err = snd_pcm_drop(tech_pvt->alsac);
+ if (err < 0) {
+ ERRORA("device [%s], snd_pcm_drop failed with error '%s'\n", SKYPIAX_P_LOG,
+ tech_pvt->alsacname, snd_strerror(err));
+ return -1;
+ }
+ err = snd_pcm_close(tech_pvt->alsac);
+ if (err < 0) {
+ ERRORA("device [%s], snd_pcm_close failed with error '%s'\n", SKYPIAX_P_LOG,
+ tech_pvt->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->alsa_period_size;
+
+ snd_pcm_hw_params_alloca(&params);
+ snd_pcm_sw_params_alloca(&swparams);
+
+ if (stream == SND_PCM_STREAM_CAPTURE) {
+ err = snd_pcm_open(&handle, tech_pvt->alsacname, stream, 0 | SND_PCM_NONBLOCK);
+ } else {
+ err = snd_pcm_open(&handle, tech_pvt->alsapname, stream, 0 | SND_PCM_NONBLOCK);
+ }
+ if (err < 0) {
+ ERRORA
+ ("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"
+ " is running?\n", SKYPIAX_P_LOG, snd_strerror(err),
+ stream == SND_PCM_STREAM_CAPTURE ? tech_pvt->alsacname : tech_pvt->alsapname);
+ return NULL;
+ }
+
+ snd_pcm_info_alloca(&info);
+
+ if ((err = snd_pcm_info(handle, info)) < 0) {
+ ERRORA("info error: %s", SKYPIAX_P_LOG, snd_strerror(err));
+ return NULL;
+ }
+
+ err = snd_pcm_nonblock(handle, 1);
+ if (err < 0) {
+ ERRORA("nonblock setting error: %s", SKYPIAX_P_LOG, snd_strerror(err));
+ return NULL;
+ }
+
+ err = snd_pcm_hw_params_any(handle, params);
+ if (err < 0) {
+ ERRORA("Broken configuration for this PCM, no configurations available: %s\n",
+ SKYPIAX_P_LOG, snd_strerror(err));
+ return NULL;
+ }
+
+ err = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
+ if (err < 0) {
+ ERRORA("Access type not available: %s\n", SKYPIAX_P_LOG, snd_strerror(err));
+ return NULL;
+ }
+ err = snd_pcm_hw_params_set_format(handle, params, celliax_format);
+ if (err < 0) {
+ ERRORA("Sample format non available: %s\n", SKYPIAX_P_LOG, snd_strerror(err));
+ return NULL;
+ }
+ err = snd_pcm_hw_params_set_channels(handle, params, 1);
+ if (err < 0) {
+ DEBUGA_SKYPE("Channels count set failed: %s\n", SKYPIAX_P_LOG, snd_strerror(err));
+ }
+#if 1
+ unsigned int chan_num;
+ err = snd_pcm_hw_params_get_channels(params, &chan_num);
+ if (err < 0) {
+ ERRORA("Channels count non available: %s\n", SKYPIAX_P_LOG, snd_strerror(err));
+ return NULL;
+ }
+ if (chan_num < 1 || chan_num > 2) {
+ ERRORA("Channels count MUST BE 1 or 2, it is: %d\n", SKYPIAX_P_LOG, chan_num);
+ ERRORA("Channels count MUST BE 1 or 2, it is: %d on %s %s\n", SKYPIAX_P_LOG, chan_num,
+ tech_pvt->alsapname, tech_pvt->alsacname);
+ return NULL;
+ } else {
+ if (chan_num == 1) {
+ if (stream == SND_PCM_STREAM_CAPTURE)
+ tech_pvt->alsa_capture_is_mono = 1;
+ else
+ tech_pvt->alsa_play_is_mono = 1;
+ } else {
+ if (stream == SND_PCM_STREAM_CAPTURE)
+ tech_pvt->alsa_capture_is_mono = 0;
+ else
+ tech_pvt->alsa_play_is_mono = 0;
+ }
+ }
+#else
+ tech_pvt->alsa_capture_is_mono = 1;
+ tech_pvt->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 && buffer_frames == 0) {
+ err = snd_pcm_hw_params_get_buffer_time_max(params, &buffer_time, 0);
+ assert(err >= 0);
+ if (buffer_time > 500000)
+ buffer_time = 500000;
+ }
+ if (period_time == 0 && period_frames == 0) {
+ if (buffer_time > 0)
+ period_time = buffer_time / 4;
+ else
+ period_frames = buffer_frames / 4;
+ }
+ if (period_time > 0)
+ err = snd_pcm_hw_params_set_period_time_near(handle, params, &period_time, 0);
+ else
+ err = snd_pcm_hw_params_set_period_size_near(handle, params, &period_frames, 0);
+ assert(err >= 0);
+ if (buffer_time > 0) {
+ err = snd_pcm_hw_params_set_buffer_time_near(handle, params, &buffer_time, 0);
+ } else {
+ err = snd_pcm_hw_params_set_buffer_size_near(handle, params, &buffer_frames);
+ }
+#endif
+
+#if 1
+ rate = tech_pvt->celliax_sound_rate;
+ err = snd_pcm_hw_params_set_rate_near(handle, params, &rate, 0);
+ if ((float) tech_pvt->celliax_sound_rate * 1.05 < rate
+ || (float) tech_pvt->celliax_sound_rate * 0.95 > rate) {
+ WARNINGA("Rate is not accurate (requested = %iHz, got = %iHz)\n", SKYPIAX_P_LOG,
+ tech_pvt->celliax_sound_rate, rate);
+ }
+
+ if (err < 0) {
+ ERRORA("Error setting rate: %s\n", SKYPIAX_P_LOG, snd_strerror(err));
+ return NULL;
+ }
+ tech_pvt->celliax_sound_rate = rate;
+
+ err = snd_pcm_hw_params_set_period_size_near(handle, params, &period_size, 0);
+
+ if (err < 0) {
+ ERRORA("Error setting period_size: %s\n", SKYPIAX_P_LOG, snd_strerror(err));
+ return NULL;
+ }
+
+ tech_pvt->alsa_period_size = period_size;
+
+ tech_pvt->alsa_buffer_size = tech_pvt->alsa_period_size * tech_pvt->alsa_periods_in_buffer;
+
+ err = snd_pcm_hw_params_set_buffer_size_near(handle, params, &tech_pvt->alsa_buffer_size);
+
+ if (err < 0) {
+ ERRORA("Error setting buffer_size: %s\n", SKYPIAX_P_LOG, snd_strerror(err));
+ return NULL;
+ }
+#endif
+
+ err = snd_pcm_hw_params(handle, params);
+ if (err < 0) {
+ ERRORA("Unable to install hw params: %s\n", SKYPIAX_P_LOG, snd_strerror(err));
+ return NULL;
+ }
+
+ snd_pcm_hw_params_get_period_size(params, &chunk_size, 0);
+ snd_pcm_hw_params_get_buffer_size(params, &buffer_size);
+ if (chunk_size == buffer_size) {
+ ERRORA("Can't use period equal to buffer size (%lu == %lu)\n", 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, &xfer_align);
+ if (err < 0) {
+ ERRORA("Unable to obtain xfer align: %s\n", SKYPIAX_P_LOG, snd_strerror(err));
+ }
+ NOTICA("xfer_align: %d\n", 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->alsa_period_size;
+ NOTICA("xfer_align: %d\n", SKYPIAX_P_LOG, xfer_align);
+
+ err = snd_pcm_sw_params_set_xfer_align(handle, swparams, xfer_align);
+ if (err < 0) {
+ ERRORA("Error setting xfer_align: %s\n", SKYPIAX_P_LOG, snd_strerror(err));
+ }
+ NOTICA("xfer_align: %d\n", SKYPIAX_P_LOG, xfer_align);
+
+ err = snd_pcm_sw_params_get_xfer_align(swparams, &xfer_align);
+ if (err < 0) {
+ ERRORA("Unable to obtain xfer align: %s\n", SKYPIAX_P_LOG, snd_strerror(err));
+ }
+ NOTICA("xfer_align: %d\n", 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 < 0) {
+ ERRORA("Error setting slep_min: %s\n", SKYPIAX_P_LOG, snd_strerror(err));
+ }
+ */
+ n = chunk_size;
+ err = snd_pcm_sw_params_set_avail_min(handle, swparams, n);
+ if (err < 0) {
+ ERRORA("Error setting avail_min: %s\n", 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 <= 0) {
+ start_threshold = n + (double) rate *start_delay / 1000000;
+ } else {
+ start_threshold = (double) rate *start_delay / 1000000;
+ }
+ if (start_threshold < 1)
+ start_threshold = 1;
+ if (start_threshold > n)
+ start_threshold = n;
+ err = snd_pcm_sw_params_set_start_threshold(handle, swparams, start_threshold);
+ if (err < 0) {
+ ERRORA("Error setting start_threshold: %s\n", SKYPIAX_P_LOG, snd_strerror(err));
+ }
+
+ if (stop_delay <= 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 < 0) {
+ ERRORA("Error setting stop_threshold: %s\n", SKYPIAX_P_LOG, snd_strerror(err));
+ }
+#if 0
+ err = snd_pcm_sw_params_set_xfer_align(handle, swparams, xfer_align);
+
+ if (err < 0) {
+ ERRORA("Error setting xfer_align: %s\n", SKYPIAX_P_LOG, snd_strerror(err));
+ }
+#endif
+
+ if (snd_pcm_sw_params(handle, swparams) < 0) {
+ ERRORA("Error installing software parameters: %s\n", SKYPIAX_P_LOG,
+ snd_strerror(err));
+ }
+
+ err = snd_pcm_poll_descriptors_count(handle);
+ if (err <= 0) {
+ ERRORA("Unable to get a poll descriptors count, error is %s\n", SKYPIAX_P_LOG,
+ snd_strerror(err));
+ return NULL;
+ }
+
+ if (err != 1) { //number of poll descriptors
+ DEBUGA_SKYPE("Can't handle more than one device\n", SKYPIAX_P_LOG);
+ return NULL;
+ }
+
+ err = snd_pcm_poll_descriptors(handle, &tech_pvt->pfd, err);
+ if (err != 1) {
+ ERRORA("snd_pcm_poll_descriptors failed, %s\n", SKYPIAX_P_LOG, snd_strerror(err));
+ return NULL;
+ }
+ DEBUGA_SKYPE("Acquired fd %d from the poll descriptor\n", SKYPIAX_P_LOG, tech_pvt->pfd.fd);
+
+ if (stream == SND_PCM_STREAM_CAPTURE) {
+ tech_pvt->celliax_sound_capt_fd = tech_pvt->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("snd_pcm_prepare failed, %s\n", SKYPIAX_P_LOG, snd_strerror(err));
+ return NULL;
+ }
+ DEBUGA_SKYPE("prepared!\n", SKYPIAX_P_LOG);
+ }
+ if (stream == SND_PCM_STREAM_CAPTURE) {
+ err = snd_pcm_start(handle);
+ if (err) {
+ ERRORA("snd_pcm_start failed, %s\n", SKYPIAX_P_LOG, snd_strerror(err));
+ return NULL;
+ }
+ DEBUGA_SKYPE("started!\n", SKYPIAX_P_LOG);
+ }
+ }
+ if (option_debug > 1) {
+ snd_output_t *output = NULL;
+ err = snd_output_stdio_attach(&output, stdout, 0);
+ if (err < 0) {
+ ERRORA("snd_output_stdio_attach failed: %s\n", SKYPIAX_P_LOG, snd_strerror(err));
+ }
+ snd_pcm_dump(handle, output);
+ }
+ if (option_debug > 1)
+ DEBUGA_SKYPE("ALSA handle = %ld\n", 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(&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->alsac);
+ if (state != SND_PCM_STATE_RUNNING) {
+ DEBUGA_SKYPE("ALSA read state is not SND_PCM_STATE_RUNNING\n", SKYPIAX_P_LOG);
+
+ if (state != SND_PCM_STATE_PREPARED) {
+ error = snd_pcm_prepare(tech_pvt->alsac);
+ if (error) {
+ ERRORA("snd_pcm_prepare failed, %s\n", SKYPIAX_P_LOG, snd_strerror(error));
+ return &f;
+ }
+ DEBUGA_SKYPE("prepared!\n", SKYPIAX_P_LOG);
+ }
+ usleep(1000);
+ error = snd_pcm_start(tech_pvt->alsac);
+ if (error) {
+ ERRORA("snd_pcm_start failed, %s\n", SKYPIAX_P_LOG, snd_strerror(error));
+ return &f;
+ }
+ DEBUGA_SKYPE("started!\n", SKYPIAX_P_LOG);
+ usleep(1000);
+ }
+
+ buf = __buf + AST_FRIENDLY_OFFSET / 2;
+ buf2 = __buf2 + ((AST_FRIENDLY_OFFSET / 2) * 2);
+
+ if (tech_pvt->alsa_capture_is_mono) {
+ r = snd_pcm_readi(tech_pvt->alsac, buf + readpos, left);
+ } else {
+ r = snd_pcm_readi(tech_pvt->alsac, buf2 + (readpos * 2), left);
+
+ int a = 0;
+ int i = 0;
+ for (i = 0; i < (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("XRUN read\n\n\n\n\n", SKYPIAX_P_LOG);
+ return &f;
+ } else if (r == -ESTRPIPE) {
+ ERRORA("-ESTRPIPE\n", SKYPIAX_P_LOG);
+ return &f;
+
+ } else if (r == -EAGAIN) {
+ DEBUGA_SKYPE("ALSA read -EAGAIN, the soundcard is not ready to be read by celliax\n",
+ SKYPIAX_P_LOG);
+ while (r == -EAGAIN) {
+ usleep(1000);
+
+ if (tech_pvt->alsa_capture_is_mono) {
+ r = snd_pcm_readi(tech_pvt->alsac, buf + readpos, left);
+ } else {
+ r = snd_pcm_readi(tech_pvt->alsac, buf2 + (readpos * 2), left);
+
+ int a = 0;
+ int i = 0;
+ for (i = 0; i < (SKYPIAX_FRAME_SIZE + AST_FRIENDLY_OFFSET / 2) * 2;) {
+ __buf[a] = (__buf2[i] + __buf2[i + 1]) / 2;
+ a++;
+ i++;
+ i++;
+ }
+ }
+
+ }
+ } else if (r < 0) {
+ WARNINGA("ALSA Read error: %s\n", SKYPIAX_P_LOG, snd_strerror(r));
+ } else if (r >= 0) {
+ //DEBUGA_SKYPE("read: r=%d, readpos=%d, left=%d, off=%d\n", 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 >= 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 &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->datalen > sizeof(sizbuf) - sizpos) {
+ ERRORA("Frame too large\n", SKYPIAX_P_LOG);
+ res = -1;
+ } else {
+ memcpy(sizbuf + sizpos, f->data, f->datalen);
+ len += f->datalen;
+ pos = 0;
+#ifdef ALSA_MONITOR
+ alsa_monitor_write(sizbuf, len);
+#endif
+ state = snd_pcm_state(tech_pvt->alsap);
+ if (state == SND_PCM_STATE_XRUN) {
+ int i;
+
+ DEBUGA_SKYPE
+ ("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",
+ SKYPIAX_P_LOG, tech_pvt->alsa_periods_in_buffer);
+ res = snd_pcm_prepare(tech_pvt->alsap);
+ if (res) {
+ ERRORA("audio play prepare failed: %s\n", SKYPIAX_P_LOG, snd_strerror(res));
+ } else {
+ res = snd_pcm_format_set_silence(celliax_format, silencebuf, len / 2);
+ if (res < 0) {
+ DEBUGA_SKYPE("Silence error %s\n", SKYPIAX_P_LOG, snd_strerror(res));
+ res = -1;
+ }
+ for (i = 0; i < (tech_pvt->alsa_periods_in_buffer - 1); i++) {
+ res = snd_pcm_writei(tech_pvt->alsap, silencebuf, len / 2);
+ if (res != len / 2) {
+ DEBUGA_SKYPE("Write returned a different quantity: %d\n", SKYPIAX_P_LOG, res);
+ res = -1;
+ } else if (res < 0) {
+ DEBUGA_SKYPE("Write error %s\n", SKYPIAX_P_LOG, snd_strerror(res));
+ res = -1;
+ }
+ }
+ }
+
+ }
+
+ res = snd_pcm_delay(tech_pvt->alsap, &delayp1);
+ if (res < 0) {
+ DEBUGA_SKYPE("Error %d on snd_pcm_delay: \"%s\"\n", SKYPIAX_P_LOG, res,
+ snd_strerror(res));
+ res = snd_pcm_prepare(tech_pvt->alsap);
+ if (res) {
+ DEBUGA_SKYPE("snd_pcm_prepare failed: '%s'\n", SKYPIAX_P_LOG, snd_strerror(res));
+ }
+ res = snd_pcm_delay(tech_pvt->alsap, &delayp1);
+ }
+
+ delayp2 = snd_pcm_avail_update(tech_pvt->alsap);
+ if (delayp2 < 0) {
+ DEBUGA_SKYPE("Error %d on snd_pcm_avail_update: \"%s\"\n", SKYPIAX_P_LOG,
+ (int) delayp2, snd_strerror(delayp2));
+
+ res = snd_pcm_prepare(tech_pvt->alsap);
+ if (res) {
+ DEBUGA_SKYPE("snd_pcm_prepare failed: '%s'\n", SKYPIAX_P_LOG, snd_strerror(res));
+ }
+ delayp2 = snd_pcm_avail_update(tech_pvt->alsap);
+ }
+
+ if ( /* delayp1 != 0 && delayp1 != 160 */
+ delayp1 < 160 || delayp2 > tech_pvt->alsa_buffer_size) {
+
+ res = snd_pcm_prepare(tech_pvt->alsap);
+ if (res) {
+ DEBUGA_SKYPE
+ ("snd_pcm_prepare failed while trying to prevent an ALSA write XRUN: %s, delayp1=%d, delayp2=%d\n",
+ SKYPIAX_P_LOG, snd_strerror(res), (int) delayp1, (int) delayp2);
+ } else {
+
+ int i;
+ for (i = 0; i < (tech_pvt->alsa_periods_in_buffer - 1); i++) {
+ res = snd_pcm_format_set_silence(celliax_format, silencebuf, len / 2);
+ if (res < 0) {
+ DEBUGA_SKYPE("Silence error %s\n", SKYPIAX_P_LOG, snd_strerror(res));
+ res = -1;
+ }
+ res = snd_pcm_writei(tech_pvt->alsap, silencebuf, len / 2);
+ if (res < 0) {
+ DEBUGA_SKYPE("Write error %s\n", SKYPIAX_P_LOG, snd_strerror(res));
+ res = -1;
+ } else if (res != len / 2) {
+ DEBUGA_SKYPE("Write returned a different quantity: %d\n", SKYPIAX_P_LOG, res);
+ res = -1;
+ }
+ }
+
+ DEBUGA_SKYPE
+ ("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",
+ SKYPIAX_P_LOG, tech_pvt->alsa_periods_in_buffer, (int) delayp1, (int) delayp2);
+ }
+
+ }
+
+ memset(sizbuf2, 0, sizeof(sizbuf2));
+ if (tech_pvt->alsa_play_is_mono) {
+ res = snd_pcm_writei(tech_pvt->alsap, sizbuf, len / 2);
+ } else {
+ int a = 0;
+ int i = 0;
+ for (i = 0; i < 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->alsap, sizbuf2, len);
+ }
+ if (res == -EPIPE) {
+ DEBUGA_SKYPE
+ ("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",
+ SKYPIAX_P_LOG, tech_pvt->alsa_periods_in_buffer, (int) delayp1, (int) delayp2);
+ res = snd_pcm_prepare(tech_pvt->alsap);
+ if (res) {
+ ERRORA("audio play prepare failed: %s\n", SKYPIAX_P_LOG, snd_strerror(res));
+ } else {
+
+ if (tech_pvt->alsa_play_is_mono) {
+ res = snd_pcm_writei(tech_pvt->alsap, sizbuf, len / 2);
+ } else {
+ int a = 0;
+ int i = 0;
+ for (i = 0; i < 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->alsap, sizbuf2, len);
+ }
+
+ }
+
+ } else {
+ if (res == -ESTRPIPE) {
+ ERRORA("You've got some big problems\n", SKYPIAX_P_LOG);
+ } else if (res == -EAGAIN) {
+ res = 0;
+ } else if (res < 0) {
+ ERRORA("Error %d on audio write: \"%s\"\n", SKYPIAX_P_LOG, res,
+ snd_strerror(res));
+ }
+ }
+ }
+
+ if (tech_pvt->audio_play_reset_period) {
+ time(&now_timestamp);
+ if ((now_timestamp - tech_pvt->audio_play_reset_timestamp) > tech_pvt->audio_play_reset_period) {
+ if (option_debug)
+ DEBUGA_SKYPE("reset audio play\n", SKYPIAX_P_LOG);
+ res = snd_pcm_wait(tech_pvt->alsap, 1000);
+ if (res < 0) {
+ ERRORA("audio play wait failed: %s\n", SKYPIAX_P_LOG, snd_strerror(res));
+ }
+ res = snd_pcm_drop(tech_pvt->alsap);
+ if (res) {
+ ERRORA("audio play drop failed: %s\n", SKYPIAX_P_LOG, snd_strerror(res));
+ }
+ res = snd_pcm_prepare(tech_pvt->alsap);
+ if (res) {
+ ERRORA("audio play prepare failed: %s\n", SKYPIAX_P_LOG, snd_strerror(res));
+ }
+ res = snd_pcm_wait(tech_pvt->alsap, 1000);
+ if (res < 0) {
+ ERRORA("audio play wait failed: %s\n", SKYPIAX_P_LOG, snd_strerror(res));
+ }
+ time(&tech_pvt->audio_play_reset_timestamp);
+ }
+ }
+ res = 0;
+ if (res > 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("Calling Skype, rdest is: %s\n", SKYPIAX_P_LOG, rdest);
+        //celliax_signaling_write(tech_pvt, "SET AGC OFF");
+        //celliax_sleep(10000);
+        //celliax_signaling_write(tech_pvt, "SET AEC OFF");
+        //celliax_sleep(10000);
+
+        sprintf(msg_to_skype, "CALL %s", rdest);
+        //if (celliax_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;
+}
+
+
+int celliax_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);
+        //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 , "plughw:0");
+ switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].alsapname , "plughw:0");
</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">                                         ("interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].X11_display=%s\n",
</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(&globals.SKYPIAX_INTERFACES[interface_id]);
+                                 if (res == -1) {
+                                         ERRORA("Failed initializing sound device\n", 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(&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->write_function(stream, "sk console is NOT yet assigned\n");
</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 *) &cmd[strlen(argv[0]) + 1]);
</del><ins>+                        //celliax_signaling_write(tech_pvt, (char *) &cmd[strlen(argv[0]) + 1]);
</ins><span class="cx">                 }
</span><span class="cx">         } else {
</span><span class="cx">                 stream->write_function(stream, "ERROR, usage: %s", SKYPIAX_SYNTAX);
</span><span class="lines">@@ -2235,7 +2243,7 @@
</span><span class="cx">                         //available_celliax_interface->ib_calls++;
</span><span class="cx">
</span><span class="cx">                         sprintf(msg_to_skype, "ALTER CALL %s TRANSFER %s", id, available_celliax_interface->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->interface_state == SKYPIAX_STATE_SELECTED) {
</span><span class="cx">                                 tech_pvt->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">                                 ("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",
</span><span class="cx">                                  SKYPIAX_P_LOG, id, tech_pvt->skype_call_id);
</span><span class="cx">                         sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", 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>