[Freeswitch-branches] [commit] r10234 - freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax
Freeswitch SVN
gmaruzz at freeswitch.org
Tue Nov 4 06:05:26 EST 2008
Author: gmaruzz
Date: Tue Nov 4 06:05:25 2008
New Revision: 10234
Modified:
freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/mod_skypiax.c
Log:
skypiax: added mod_alsa to skeleton
Modified: freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/mod_skypiax.c
==============================================================================
--- freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/mod_skypiax.c (original)
+++ freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/mod_skypiax.c Tue Nov 4 06:05:25 2008
@@ -1855,1484 +1855,3522 @@
#endif /* MOD_PORTAUDIO */
+#ifdef SKYPIAX_H
+
+//indent -gnu -ts4 -br -brs -cdw -lp -ce -nbfda -npcs -nprs -npsl -nbbo -saf -sai -saw -cs -bbo -nhnl -nut -sob -l90
+#ifndef _SKYPIAX_H_
+#define _SKYPIAX_H_
+
+#ifndef SKYPIAX_SVN_VERSION
+#define SKYPIAX_SVN_VERSION "????NO_REVISION???"
+#endif
+
+#include <asterisk/version.h> /* needed here for conditional compilation on version.h */
+ /* the following #defs are for LINUX */
+#ifndef __CYGWIN__
+#ifndef ASTERISK_VERSION_1_6
+#ifndef ASTERISK_VERSION_1_4
+#ifndef ASTERISK_VERSION_1_2
+#define ASTERISK_VERSION_1_4
+#if(ASTERISK_VERSION_NUM == 999999)
+#undef ASTERISK_VERSION_1_4
+#elif(ASTERISK_VERSION_NUM < 10400)
+#undef ASTERISK_VERSION_1_4
+#endif /* ASTERISK_VERSION_NUM == 999999 || ASTERISK_VERSION_NUM < 10400 */
+#endif /* ASTERISK_VERSION_1_2 */
+#endif /* ASTERISK_VERSION_1_4 */
+#endif /* ASTERISK_VERSION_1_6 */
+#ifdef ASTERISK_VERSION_1_2
+#undef ASTERISK_VERSION_1_4
+#endif /* ASTERISK_VERSION_1_2 */
+#ifdef ASTERISK_VERSION_1_6
+#define ASTERISK_VERSION_1_4
+#endif /* ASTERISK_VERSION_1_6 */
+#define SKYPIAX_SKYPE
+#define WANT_SKYPE_X11
+#endif /* NOT __CYGWIN__ */
+ /* the following #defs are for WINDOWS */
+#ifdef __CYGWIN__
+#undef ASTERISK_VERSION_1_4
+#undef ASTERISK_VERSION_1_6
+#define SKYPIAX_SKYPE
+#undef WANT_SKYPE_X11
+#endif /* __CYGWIN__ */
+
+/* INCLUDES */
+#ifdef ASTERISK_VERSION_1_6
+#include <asterisk.h> /* some asterisk-devel package do not contains asterisk.h, but seems that is needed for the 1.6 series, at least from trunk */
+#endif /* ASTERISK_VERSION_1_6 */
+#include <unistd.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <math.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <string.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <ctype.h>
+#ifndef ASTERISK_VERSION_1_4
+#include <stdlib.h>
+#include <stdio.h>
+#endif /* ASTERISK_VERSION_1_4 */
+#include <asterisk/frame.h>
+#include <asterisk/channel.h>
+#include <asterisk/module.h>
+#include <asterisk/options.h>
+#include <asterisk/pbx.h>
+#include <asterisk/config.h>
+#include <asterisk/cli.h>
+#include <asterisk/causes.h>
+#include <asterisk/endian.h>
+#include <asterisk/lock.h>
+#include <asterisk/devicestate.h>
+#include <asterisk/file.h>
+#include <asterisk/say.h>
+#ifdef ASTERISK_VERSION_1_6
+#include <asterisk/astobj2.h>
+#include <asterisk/paths.h>
+#endif /* ASTERISK_VERSION_1_6 */
+#ifdef ASTERISK_VERSION_1_4
+#include <asterisk/stringfields.h>
+#include <asterisk/abstract_jb.h>
+#include <asterisk/logger.h>
+#include <asterisk/utils.h>
+#endif /* ASTERISK_VERSION_1_4 */
+#ifdef ASTERISK_VERSION_1_2
+#include <asterisk/utils.h>
+#include <asterisk/logger.h>
+#endif /* ASTERISK_VERSION_1_2 */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+//#include "skypiax_spandsp.h"
+#ifdef __CYGWIN__
+#include <windows.h>
+#endif /* __CYGWIN__ */
+#ifdef WANT_SKYPE_X11
+#include <X11/Xlib.h>
+#include <X11/Xlibint.h>
+#include <X11/Xatom.h>
+#endif /* WANT_SKYPE_X11 */
+#ifndef AST_DIGIT_ANYDIG
+#define AST_DIGIT_ANYDIG "0123456789*#"
+#else
+#warning Please review Skypiax AST_DIGIT_ANYDIG
+#endif
+#ifndef _ASTERISK_H
+#define AST_CONFIG_MAX_PATH 255 /* defined in asterisk.h, but some asterisk-devel package do not contains asterisk.h */
+extern char ast_config_AST_CONFIG_DIR[AST_CONFIG_MAX_PATH];
+int ast_register_atexit(void (*func) (void)); /* in asterisk.h, but some asterisk-devel package do not contains asterisk.h */
+void ast_unregister_atexit(void (*func) (void)); /* in asterisk.h, but some asterisk-devel package do not contains asterisk.h */
+#endif
+
+/* DEFINITIONS */
+/* LUIGI RIZZO's magic */
+/* boost support. BOOST_SCALE * 10 ^(BOOST_MAX/20) must
+ * be representable in 16 bits to avoid overflows.
+ */
+#define BOOST_SCALE (1<<9)
+#define BOOST_MAX 40 /* slightly less than 7 bits */
+/* call flow from the device */
+#define CALLFLOW_CALL_IDLE AST_STATE_DOWN
+#define CALLFLOW_INCOMING_RING AST_STATE_RING
+#define CALLFLOW_CALL_DIALING AST_STATE_DIALING
+#define CALLFLOW_CALL_LINEBUSY AST_STATE_BUSY
+#define CALLFLOW_CALL_ACTIVE 300
+#define CALLFLOW_INCOMING_HANGUP 100
+#define CALLFLOW_CALL_RELEASED 101
+#define CALLFLOW_CALL_NOCARRIER 102
+#define CALLFLOW_CALL_INFLUX 103
+#define CALLFLOW_CALL_INCOMING 104
+#define CALLFLOW_CALL_FAILED 105
+#define CALLFLOW_CALL_NOSERVICE 106
+#define CALLFLOW_CALL_OUTGOINGRESTRICTED 107
+#define CALLFLOW_CALL_SECURITYFAIL 108
+#define CALLFLOW_CALL_NOANSWER 109
+#define CALLFLOW_STATUS_FINISHED 110
+#define CALLFLOW_STATUS_CANCELLED 111
+#define CALLFLOW_STATUS_FAILED 112
+#define CALLFLOW_STATUS_REFUSED 113
+#define CALLFLOW_STATUS_RINGING 114
+#define CALLFLOW_STATUS_INPROGRESS 115
+#define CALLFLOW_STATUS_UNPLACED 116
+#define CALLFLOW_STATUS_ROUTING 117
+#define CALLFLOW_STATUS_EARLYMEDIA 118
+#define AST_STATE_HANGUP_REQUESTED 200
+ //FIXME CALLFLOW_INCOMING_CALLID to be removed
+#define CALLFLOW_INCOMING_CALLID 1019
+/* debugging bitmask */
+#define DEBUG_SOUND 1
+#define DEBUG_SERIAL 2
+#define DEBUG_SKYPE 4
+#define DEBUG_AT 8
+#define DEBUG_FBUS2 16
+#define DEBUG_CALL 32
+#define DEBUG_LOCKS 64
+#define DEBUG_PBX 128
+#define DEBUG_MONITORLOCKS 256
+#define DEBUG_ALL DEBUG_SOUND|DEBUG_SERIAL|DEBUG_SKYPE|DEBUG_AT|DEBUG_FBUS2|DEBUG_CALL|DEBUG_PBX|DEBUG_LOCKS|DEBUG_MONITORLOCKS
+/* wrappers for ast_log */
+#define DEBUGA_SOUND(...) if (skypiax_debug & DEBUG_SOUND) ast_log(LOG_DEBUG, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_SOUND %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
+#define DEBUGA_SERIAL(...) if (skypiax_debug & DEBUG_SERIAL) ast_log(LOG_DEBUG, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_SERIAL %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
+#define DEBUGA_SKYPE(...) if (skypiax_debug & DEBUG_SKYPE) ast_log(LOG_DEBUG, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_SKYPE %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
+#define DEBUGA_AT(...) if (skypiax_debug & DEBUG_AT) ast_log(LOG_DEBUG, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_AT %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
+#define DEBUGA_FBUS2(...) if (skypiax_debug & DEBUG_FBUS2) ast_log(LOG_DEBUG, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_FBUS2 %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
+#define DEBUGA_CALL(...) if (skypiax_debug & DEBUG_CALL) ast_log(LOG_DEBUG, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_CALL %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
+#define DEBUGA_PBX(...) if (skypiax_debug & DEBUG_PBX) ast_log(LOG_DEBUG, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_PBX %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
+#define ERRORA(...) ast_log(LOG_ERROR, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][ERROR %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
+#define NOTICA(...) ast_log(LOG_NOTICE, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][NOTICE %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
+#define WARNINGA(...) ast_log(LOG_WARNING, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][WARNING %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
+/* macros for logging */
+#define SKYPIAX_P_LOG p ? p->owner : NULL, (unsigned long)pthread_self(), __LINE__, p ? p->name ? p->name : "none" : "none", p ? p->owner ? p->owner->_state : -1 : -1, p ? p->interface_state : -1, p ? p->skype_callflow : -1
+#define SKYPIAX_TMP_LOG tmp ? tmp->owner : NULL, (unsigned long)pthread_self(), __LINE__, tmp ? tmp->name ? tmp->name : "none" : "none", tmp ? tmp->owner ? tmp->owner->_state : -1 : -1, tmp ? tmp->interface_state : -1, tmp ? tmp->skype_callflow : -1
+/* logging wrappers for ast_mutex_lock and ast_mutex_unlock */
+#define LOKKA(x) if (skypiax_debug & DEBUG_LOCKS) ast_log(LOG_DEBUG, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_LOCKS %-5d][%-10s][%2d,%2d,%2d] going to lock %p (%s)\n", SKYPIAX_P_LOG, x, x == &skypiax_monlock ? "MONLOCK" : x == &skypiax_iflock ? "IFLOCK" : x == &skypiax_usecnt_lock ? "USECNT_LOCK" : "?????"); if (ast_mutex_lock(x)) ast_log(LOG_ERROR, "ast_mutex_lock failed, BAD\n"); if (skypiax_debug & DEBUG_LOCKS) ast_log(LOG_DEBUG, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_LOCKS %-5d][%-10s][%2d,%2d,%2d] locked %p (%s)\n", SKYPIAX_P_LOG, x, x == &skypiax_monlock ? "MONLOCK" : x == &skypiax_iflock ? "IFLOCK" : x == &skypiax_usecnt_lock ? "USECNT_LOCK" : "?????");
+#define UNLOCKA(x) if (skypiax_debug & DEBUG_LOCKS) ast_log(LOG_DEBUG, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_LOCKS %-5d][%-10s][%2d,%2d,%2d] going to unlock %p (%s)\n", SKYPIAX_P_LOG, x, x == &skypiax_monlock ? "MONLOCK" : x == &skypiax_iflock ? "IFLOCK" : x == &skypiax_usecnt_lock ? "USECNT_LOCK" : "?????"); if (ast_mutex_unlock(x)) ast_log(LOG_ERROR, "ast_mutex_lock failed, BAD\n"); if (skypiax_debug & DEBUG_LOCKS) ast_log(LOG_DEBUG, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_LOCKS %-5d][%-10s][%2d,%2d,%2d] unlocked %p (%s)\n", SKYPIAX_P_LOG, x, x == &skypiax_monlock ? "MONLOCK" : x == &skypiax_iflock ? "IFLOCK" : x == &skypiax_usecnt_lock ? "USECNT_LOCK" : "?????");
+#define PUSHA_UNLOCKA(x) pthread_cleanup_push(skypiax_unlocka_log, (void *) x);
+#define POPPA_UNLOCKA(x) pthread_cleanup_pop(0);
+#define MONITORLOKKA(x) if (skypiax_debug & DEBUG_MONITORLOCKS) ast_log(LOG_DEBUG, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_MONITORLOCKS %-5d][%-10s][%2d,%2d,%2d] going to lock %p (%s)\n", SKYPIAX_P_LOG, x, x == &skypiax_monlock ? "MONLOCK" : x == &skypiax_iflock ? "IFLOCK" : x == &skypiax_usecnt_lock ? "USECNT_LOCK" : "?????"); if (ast_mutex_lock(x)) ast_log(LOG_ERROR, "ast_mutex_lock failed, BAD\n"); if (skypiax_debug & DEBUG_MONITORLOCKS) ast_log(LOG_DEBUG, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_MONITORLOCKS %-5d][%-10s][%2d,%2d,%2d] locked %p (%s)\n", SKYPIAX_P_LOG, x, x == &skypiax_monlock ? "MONLOCK" : x == &skypiax_iflock ? "IFLOCK" : x == &skypiax_usecnt_lock ? "USECNT_LOCK" : "?????");
+#define MONITORUNLOCKA(x) if (skypiax_debug & DEBUG_MONITORLOCKS) ast_log(LOG_DEBUG, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_MONITORLOCKS %-5d][%-10s][%2d,%2d,%2d] going to unlock %p (%s)\n", SKYPIAX_P_LOG, x, x == &skypiax_monlock ? "MONLOCK" : x == &skypiax_iflock ? "IFLOCK" : x == &skypiax_usecnt_lock ? "USECNT_LOCK" : "?????"); if (ast_mutex_unlock(x)) ast_log(LOG_ERROR, "ast_mutex_lock failed, BAD\n"); if (skypiax_debug & DEBUG_MONITORLOCKS) ast_log(LOG_DEBUG, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_MONITORLOCKS %-5d][%-10s][%2d,%2d,%2d] unlocked %p (%s)\n", SKYPIAX_P_LOG, x, x == &skypiax_monlock ? "MONLOCK" : x == &skypiax_iflock ? "IFLOCK" : x == &skypiax_usecnt_lock ? "USECNT_LOCK" : "?????");
+/* macros used for config file parsing (luigi rizzo)*/
+#define M_BOOL(tag, dst) M_F(tag, (dst) = ast_true(__val) )
+#define M_END(x) x;
+#define M_F(tag, f) if (!strcasecmp((__s), tag)) { f; } else
+#ifdef ASTERISK_VERSION_1_6
+#define M_START(var, val) const char *__s = var; const char *__val = val;
+#else
+#define M_START(var, val) char *__s = var; char *__val = val;
+#endif /* ASTERISK_VERSION_1_6 */
+#define M_STR(tag, dst) M_F(tag, ast_copy_string(dst, __val, sizeof(dst)))
+#define M_UINT(tag, dst) M_F(tag, (dst) = strtoul(__val, NULL, 0) )
+
+#define SKYPIAX_FRAME_SIZE 160
+
+/* SKYPIAX INTERNAL STRUCTS */
+/*!
+ * \brief structure for exchanging messages with the skype client
+ */
+#ifdef WANT_SKYPE_X11
+struct AsteriskHandles {
+ Window skype_win;
+ Display *disp;
+ Window win;
+ int fdesc[2];
+};
+#else /* WANT_SKYPE_X11 */
+struct AsteriskHandles {
+ HWND win32_hInit_MainWindowHandle;
+ HWND win32_hGlobal_SkypeAPIWindowHandle;
+ int fdesc[2];
+};
+#endif /* WANT_SKYPE_X11 */
+
+/*!
+ * \brief PVT structure for a skypiax interface (channel), created by skypiax_mkif
+ */
+struct skypiax_pvt {
+ char *name; /*!< \brief 'name' of the interface (channel) */
+ int interface_state; /*!< \brief 'state' of the interface (channel) */
+ struct ast_channel *owner; /*!< \brief channel we belong to, possibly NULL */
+ struct skypiax_pvt *next; /*!< \brief Next interface (channel) in list */
+ char context[AST_MAX_EXTENSION]; /*!< \brief default Asterisk dialplan context for this interface */
+ char language[MAX_LANGUAGE]; /*!< \brief default Asterisk dialplan language for this interface */
+ char exten[AST_MAX_EXTENSION]; /*!< \brief default Asterisk dialplan extension for this interface */
+ int skypiax_sound_rate; /*!< \brief rate of the sound device, in Hz, eg: 8000 */
+ int skypiax_sound_capt_fd; /*!< \brief file descriptor for sound capture dev */
+ char callid_name[50];
+ char callid_number[50];
+ pthread_t controldev_thread; /*!< \brief serial control thread for this interface, running during the call */
+ double playback_boost;
+ double capture_boost;
+ int stripmsd;
+ pthread_t skype_thread;
+ struct AsteriskHandles AsteriskHandlesAst;
+ char skype_call_id[512];
+ int skype_call_ongoing;
+ char skype_friends[4096];
+ char skype_fullname[512];
+ char skype_displayname[512];
+ int skype_callflow; /*!< \brief 'callflow' of the skype interface (as opposed to phone interface) */
+ int skype; /*!< \brief config flag, bool, Skype support on this interface (0 if false, -1 if true) */
+ int control_to_send;
+ int audiopipe[2];
+ int audioskypepipe[2];
+ pthread_t tcp_srv_thread;
+ pthread_t tcp_cli_thread;
+ short audiobuf[160];
+ int audiobuf_is_loaded;
+
+ //int phonebook_listing;
+ //int phonebook_querying;
+ //int phonebook_listing_received_calls;
+
+ //int phonebook_first_entry;
+ //int phonebook_last_entry;
+ //int phonebook_number_lenght;
+ //int phonebook_text_lenght;
+ FILE *phonebook_writing_fp;
+ int skypiax_dir_entry_extension_prefix;
+
+};
+/* FUNCTIONS */
+
+/* module helpers functions */
+int load_module(void);
+int unload_module(void);
+int usecount(void);
+char *description(void);
+char *key(void);
+
+/* chan_skypiax internal functions */
+void skypiax_unlocka_log(void *x);
+
+void *do_skype_thread(void *data);
+//int skypiax2skype(struct ast_channel *c, void *data);
+//int skype2skypiax(struct ast_channel *c, void *data);
+//void skypiax_skype_disconnect(void);
+int skypiax_skype_write(struct skypiax_pvt *p, char *msg_to_skype);
+int skypiax_skype_read(struct skypiax_pvt *p);
+int skypiax_console_skype(int fd, int argc, char *argv[]);
+#ifdef WANT_SKYPE_X11
+int X11_errors_handler(Display * dpy, XErrorEvent * err);
+int skypiax_skype_send_message(struct AsteriskHandles *AsteriskHandlesAst,
+ const char *message_P);
+int skypiax_skype_present(Display * disp);
+void skypiax_skype_clean_disp(void *data);
+#endif /* WANT_SKYPE_X11 */
+#ifdef __CYGWIN__
+int win32_Initialize_CreateWindowClass(void);
+void win32_DeInitialize_DestroyWindowClass(void);
+int win32_Initialize_CreateMainWindow(void);
+void win32_DeInitialize_DestroyMainWindow(void);
+#endif /* __CYGWIN__ */
+
+/* CHAN_SKYPIAX.C */
+int skypiax_queue_control(struct ast_channel *chan, int control);
+struct skypiax_pvt *skypiax_console_find_desc(char *dev);
+int skypiax_serial_call(struct skypiax_pvt *p, char *dstr);
+
+/* FUNCTIONS */
+/* PBX interface functions */
+struct ast_channel *skypiax_request(const char *type, int format, void *data, int *cause);
+int skypiax_answer(struct ast_channel *c);
+int skypiax_hangup(struct ast_channel *c);
+int skypiax_call(struct ast_channel *c, char *idest, int timeout);
+struct ast_frame *skypiax_read(struct ast_channel *chan);
+int skypiax_write(struct ast_channel *c, struct ast_frame *f);
+int skypiax_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
+#ifndef ASTERISK_VERSION_1_4
+int skypiax_indicate(struct ast_channel *c, int cond);
+#else
+int skypiax_indicate(struct ast_channel *c, int cond, const void *data, size_t datalen);
+#endif
+int skypiax_devicestate(void *data);
+#ifdef ASTERISK_VERSION_1_4
+int skypiax_senddigit_begin(struct ast_channel *ast, char digit);
+int skypiax_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration);
+#else /* ASTERISK_VERSION_1_4 */
+int skypiax_senddigit(struct ast_channel *ast, char digit);
+#endif /* ASTERISK_VERSION_1_4 */
+
+/* chan_skypiax internal functions */
+
+struct skypiax_pvt *skypiax_mkif(struct ast_config *cfg, char *ctg,
+ int is_first_category);
+struct ast_channel *skypiax_new(struct skypiax_pvt *p, int state, char *context);
+int skypiax_restart_monitor(void);
+void *skypiax_do_monitor(void *data);
+int skypiax_sound_boost(struct ast_frame *f, double boost);
+int skypiax_sound_init(struct skypiax_pvt *p);
+int skypiax_sound_shutdown(struct skypiax_pvt *p);
+struct ast_frame *skypiax_sound_read(struct skypiax_pvt *p);
+int skypiax_sound_write(struct skypiax_pvt *p, struct ast_frame *f);
+void *skypiax_do_controldev_thread(void *data);
+#ifdef ASTERISK_VERSION_1_6
+void skypiax_store_boost(const char *s, double *boost);
+#else
+void skypiax_store_boost(char *s, double *boost);
+#endif /* ASTERISK_VERSION_1_6 */
+int skypiax_console_set_active(int fd, int argc, char *argv[]);
+int skypiax_console_hangup(int fd, int argc, char *argv[]);
+int skypiax_console_playback_boost(int fd, int argc, char *argv[]);
+int skypiax_console_capture_boost(int fd, int argc, char *argv[]);
+int skypiax_console_skypiax(int fd, int argc, char *argv[]);
+int skypiax_console_dial(int fd, int argc, char *argv[]);
+int skypiax_skypeaudio_init(struct skypiax_pvt *p);
+struct ast_frame *skypiax_skypeaudio_read(struct skypiax_pvt *p);
+void *skypiax_do_tcp_srv_thread(void *data);
+int skypiax_skypeaudio_write(struct skypiax_pvt *p, struct ast_frame *f);
+void *skypiax_do_tcp_cli_thread(void *data);
+int skypiax_skype_call(struct skypiax_pvt *p, char *idest, int timeout);
+int skypiax_console_skypiax_dir_import(int fd, int argc, char *argv[]);
+
+#endif /* _SKYPIAX_H_ */
+#endif /* SKYPIAX_H */
+#ifdef CHAN_SKYPIAX
+
+//indent -gnu -ts4 -br -brs -cdw -lp -ce -nbfda -npcs -nprs -npsl -nbbo -saf -sai -saw -cs -bbo -nhnl -nut -sob -l90
+#include "skypiax.h"
+
+/* LOCKS */
+/*! \brief Protect the skypiax_usecnt */
+AST_MUTEX_DEFINE_STATIC(skypiax_usecnt_lock);
+/*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
+ * when it's doing something critical. */
+AST_MUTEX_DEFINE_STATIC(skypiax_monlock);
+/*! \brief Protect the interfaces list */
+AST_MUTEX_DEFINE_STATIC(skypiax_iflock);
+
+/* GLOBAL VARIABLES */
+char skypiax_console_active_array[50] = "";
+char *skypiax_console_active = skypiax_console_active_array;
+/*! \brief Count of active channels for this module */
+int skypiax_usecnt = 0;
+int skypiax_debug = 0;
+/*! \brief This is the thread for the monitor which checks for input on the channels
+ * which are not currently in use. */
+pthread_t skypiax_monitor_thread = AST_PTHREADT_NULL;
+pthread_t skypiax_monitor_audio_thread = AST_PTHREADT_NULL;
+
+/* CONSTANTS */
+/*! \brief Textual description for this module */
+const char skypiax_desc[] = "Skypiax, Skype Driver";
+/*! \brief Textual type for this module */
+const char skypiax_type[] = "Skypiax";
+/*! \brief Name of configuration file for this module */
+const char skypiax_config[] = "skypiax.conf";
+
+char skypiax_console_skypiax_usage[] =
+ " \n" "chan_skypiax commands info\n" " \n"
+ " chan_skypiax adds to Asterisk the following CLI commands:\n" " \n"
+ " CLI COMMANDS:\n" " skypiax_hangup\n" " skypiax_dial\n"
+ " skypiax_console\n" " skypiax_playback_boost\n"
+ " skypiax_capture_boost\n" " skypiax_skype\n"
+ " skypiax_dir_import\n" "\n"
+ " You can type 'help [command]' to obtain more specific info on usage.\n"
+ " \n";
+char skypiax_console_hangup_usage[] =
+ "Usage: skypiax_hangup\n"
+ " Hangs up any call currently placed on the \"current\" skypiax_console (Skypiax) channel.\n"
+ " Enter 'help skypiax_console' on how to change the \"current\" skypiax_console\n";
+char skypiax_console_playback_boost_usage[] =
+ "Usage: skypiax_playback_boost [value]\n"
+ " Shows or set the value of boost applied to the outgoing sound (voice). Possible values are: 0 (no boost applied), -40 to 40 (negative to positive range, in db). Without specifying a value, it just shows the current value. The value is for the \"current\" skypiax_console (Skypiax) channel.\n"
+ " Enter 'help skypiax_console' on how to change the \"current\" skypiax_console\n";
+char skypiax_console_capture_boost_usage[] =
+ "Usage: skypiax_capture_boost [value]\n"
+ " Shows or set the value of boost applied to the incoming sound (voice). Possible values are: 0 (no boost applied), -40 to 40 (negative to positive range, in db). Without specifying a value, it just shows the current value. The value is for the \"current\" skypiax_console (Skypiax) channel.\n"
+ " Enter 'help skypiax_console' on how to change the \"current\" skypiax_console\n";
+
+char skypiax_console_dial_usage[] =
+ "Usage: skypiax_dial [DTMFs]\n"
+ " Dials a given DTMF string in the call currently placed on the\n"
+ " \"current\" skypiax_console (Skypiax) channel.\n"
+ " Enter 'help skypiax_console' on how to change the \"current\" skypiax_console\n";
+
+char skypiax_console_skypiax_console_usage[] =
+ "Usage: skypiax_console [interface] | [show]\n"
+ " If used without a parameter, displays which interface is the \"current\"\n"
+ " skypiax_console. If a device is specified, the \"current\" skypiax_console is changed to\n"
+ " the interface specified.\n"
+ " If the parameter is \"show\", the available interfaces are listed\n";
+
+char skypiax_console_skype_usage[] =
+ "Usage: skypiax_skype [command string]\n"
+ " Send the 'command string' skype_msg to the Skype client connected to the \"current\" skypiax_console (Skypiax) channel.\n"
+ " Enter 'help skypiax_console' on how to change the \"current\" skypiax_console\n";
+
+char skypiax_console_skypiax_dir_import_usage[] =
+ "Usage: skypiax_dir_import [add | replace]\n"
+ " Write in the directoriax.conf config file all the entries found in 'Contacts' list of the Skype client connected to the \"current\" skypiax_console.\n"
+ " You can choose between 'add' to the end of the directoriax.conf file, or 'replace' the whole file with this new content.\n"
+ " Enter 'help skypiax_console' on how to change the \"current\" skypiax_console\n";
+
+/*! \brief Definition of this channel for PBX channel registration */
+const struct ast_channel_tech skypiax_tech = {
+ .type = skypiax_type,
+ .description = skypiax_desc,
+ .capabilities = AST_FORMAT_SLINEAR,
+ .requester = skypiax_request,
+ .hangup = skypiax_hangup,
+ .answer = skypiax_answer,
+ .read = skypiax_read,
+ .call = skypiax_call,
+ .write = skypiax_write,
+ .indicate = skypiax_indicate,
+ .fixup = skypiax_fixup,
+ .devicestate = skypiax_devicestate,
+#ifdef ASTERISK_VERSION_1_4
+ .send_digit_begin = skypiax_senddigit_begin,
+ .send_digit_end = skypiax_senddigit_end,
+#else /* ASTERISK_VERSION_1_4 */
+ .send_digit = skypiax_senddigit,
+#endif /* ASTERISK_VERSION_1_4 */
+};
+
+/*! \brief fake skypiax_pvt structure values,
+ * just for logging purposes */
+struct skypiax_pvt skypiax_log_struct = {
+ .name = "none",
+};
+
+/*! \brief Default skypiax_pvt structure values,
+ * used by skypiax_mkif to initialize the interfaces */
+struct skypiax_pvt skypiax_default = {
+ .interface_state = AST_STATE_DOWN,
+ .skype_callflow = 0,
+ .context = "default",
+ .language = "en",
+ .exten = "s",
+ .next = NULL,
+ .owner = NULL,
+ .controldev_thread = AST_PTHREADT_NULL,
+ .skypiax_sound_rate = 8000,
+ .skypiax_sound_capt_fd = -1,
+ .capture_boost = 0,
+ .playback_boost = 0,
+ .stripmsd = 0,
+ .skype = 0,
+ .skypiax_dir_entry_extension_prefix = 6,
+};
+
+/*!
+ * \brief PVT structure for a skypiax interface (channel), created by skypiax_mkif
+ */
+struct skypiax_pvt *skypiax_iflist = NULL;
+
+struct ast_cli_entry myclis[] = {
+ {{"skypiax_hangup", NULL}, skypiax_console_hangup,
+ "Hangup a call on the skypiax_console",
+ skypiax_console_hangup_usage},
+ {{"skypiax_playback_boost", NULL}, skypiax_console_playback_boost, "playback boost",
+ skypiax_console_playback_boost_usage},
+ {{"skypiax_capture_boost", NULL}, skypiax_console_capture_boost, "capture boost",
+ skypiax_console_capture_boost_usage},
+ {{"skypiax_usage", NULL}, skypiax_console_skypiax, "chan_skypiax commands info",
+ skypiax_console_skypiax_usage},
+ {{"skypiax_skype", NULL}, skypiax_console_skype, "Skype msg",
+ skypiax_console_skype_usage},
+ {{"skypiax_dial", NULL}, skypiax_console_dial,
+ "Dial an extension on the skypiax_console",
+ skypiax_console_dial_usage},
+ {{"skypiax_console", NULL}, skypiax_console_set_active,
+ "Sets/displays active skypiax_console",
+ skypiax_console_skypiax_console_usage},
+ {{"skypiax_dir_import", NULL}, skypiax_console_skypiax_dir_import,
+ "Write the directoriax.conf file, used by directoriax app",
+ skypiax_console_skypiax_dir_import_usage},
+};
+
+/* IMPLEMENTATION */
+
+void skypiax_unlocka_log(void *x)
+{
+ ast_mutex_t *y;
+ y = x;
+ int i;
+
+ for (i = 0; i < 5; i++) { //let's be generous
+
+ ast_log(LOG_DEBUG,
+ SKYPIAX_SVN_VERSION
+ "[%-7lx] I'm a dying thread, and I'm to go unlocking mutex %p for the %dth time\n",
+ (unsigned long int) pthread_self(), y, i);
+
+ ast_mutex_unlock(y);
+ }
+ ast_log(LOG_DEBUG,
+ SKYPIAX_SVN_VERSION
+ "[%-7lx] I'm a dying thread, I've finished unlocking mutex %p\n",
+ (unsigned long int) pthread_self(), y);
+}
+
+int skypiax_queue_control(struct ast_channel *c, int control)
+{
+ struct skypiax_pvt *p = c->tech_pvt;
+
+ if (option_debug > 10) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+/* queue the frame */
+ if (p)
+ p->control_to_send = control;
+ else {
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return 0;
+ }
+ DEBUGA_PBX("Queued CONTROL FRAME %d\n", SKYPIAX_P_LOG, control);
+
+/* wait for the frame to be sent */
+ while (p->control_to_send)
+ usleep(1);
+
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return 0;
+}
+
+int skypiax_devicestate(void *data)
+{
+ struct skypiax_pvt *p = NULL;
+ char *name = data;
+ int res = AST_DEVICE_INVALID;
+
+ if (option_debug > 10) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+ if (!data) {
+ ERRORA("Devicestate requested with no data\n", SKYPIAX_P_LOG);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return res;
+ }
+
+ /* lock the interfaces' list */
+ LOKKA(&skypiax_iflock);
+ /* make a pointer to the first interface in the interfaces list */
+ p = skypiax_iflist;
+ /* Search for the requested interface and verify if is unowned */
+ while (p) {
+ size_t length = strlen(p->name);
+ /* is this the requested interface? */
+ if (strncmp(name, p->name, length) == 0) {
+ /* is this interface unowned? */
+ if (!p->owner) {
+ res = AST_DEVICE_NOT_INUSE;
+ DEBUGA_PBX("Interface is NOT OWNED by a channel\n", SKYPIAX_P_LOG);
+ } else {
+ /* interface owned by a channel */
+ res = AST_DEVICE_INUSE;
+ DEBUGA_PBX("Interface is OWNED by a channel\n", SKYPIAX_P_LOG);
+ }
+
+ /* we found the requested interface, bail out from the while loop */
+ break;
+ }
+ /* not yet found, next please */
+ p = p->next;
+ }
+ /* unlock the interfaces' list */
+ UNLOCKA(&skypiax_iflock);
+
+ if (res == AST_DEVICE_INVALID) {
+ ERRORA("Checking device state for interface [%s] returning AST_DEVICE_INVALID\n",
+ SKYPIAX_P_LOG, name);
+ }
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return res;
+}
+
+#ifndef ASTERISK_VERSION_1_4
+int skypiax_indicate(struct ast_channel *c, int cond)
+#else
+int skypiax_indicate(struct ast_channel *c, int cond, const void *data, size_t datalen)
+#endif
+{
+ struct skypiax_pvt *p = c->tech_pvt;
+ int res = 0;
+
+ if (option_debug > 10) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+ NOTICA("Let's INDICATE %d\n", SKYPIAX_P_LOG, cond);
+
+ switch (cond) {
+ case AST_CONTROL_BUSY:
+ case AST_CONTROL_CONGESTION:
+ case AST_CONTROL_RINGING:
+ case -1:
+ res = -1; /* Ask for inband indications */
+ break;
+ case AST_CONTROL_PROGRESS:
+ case AST_CONTROL_PROCEEDING:
+ case AST_CONTROL_VIDUPDATE:
+ case AST_CONTROL_HOLD:
+ case AST_CONTROL_UNHOLD:
+#ifdef ASTERISK_VERSION_1_4
+ case AST_CONTROL_SRCUPDATE:
+#endif /* ASTERISK_VERSION_1_4 */
+ break;
+ default:
+ WARNINGA("Don't know how to display condition %d on %s\n", SKYPIAX_P_LOG, cond,
+ c->name);
+ /* The core will play inband indications for us if appropriate */
+ res = -1;
+ }
+
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return res;
+}
+
+/*! \brief PBX interface function -build skypiax pvt structure
+ * skypiax calls initiated by the PBX arrive here */
+struct ast_channel *skypiax_request(const char *type, int format, void *data, int *cause)
+{
+ struct skypiax_pvt *p = NULL;
+ struct ast_channel *tmp = NULL;
+ char *name = data;
+
+ if (option_debug > 10) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+
+ DEBUGA_PBX("Try to request type: %s, name: %s, cause: %d," " format: %d\n",
+ SKYPIAX_P_LOG, type, name, *cause, format);
+
+ if (!data) {
+ ERRORA("Channel requested with no data\n", SKYPIAX_P_LOG);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return NULL;
+ }
+
+ /* lock the interfaces' list */
+ LOKKA(&skypiax_iflock);
+ /* make a pointer to the first interface in the interfaces list */
+ p = skypiax_iflist;
+ /* Search for the requested interface and verify if is unowned and format compatible */
+ //TODO implement groups a la chan_zap
+ while (p) {
+ size_t length = strlen(p->name);
+ /* is this the requested interface? */
+ if (strncmp(name, p->name, length) == 0) {
+ /* is the requested format supported by this interface? */
+ if ((format & AST_FORMAT_SLINEAR) != 0) {
+ /* is this interface unowned? */
+ if (!p->owner) {
+ DEBUGA_PBX("Requesting: %s, name: %s, format: %d\n", SKYPIAX_P_LOG, type, name,
+ format);
+ /* create a new channel owning this interface */
+ tmp = skypiax_new(p, AST_STATE_DOWN, p->context);
+ if (!tmp) {
+ /* the channel was not created, probable memory allocation error */
+ *cause = AST_CAUSE_SWITCH_CONGESTION;
+ }
+ } else {
+ /* interface owned by another channel */
+ WARNINGA("owned by another channel\n", SKYPIAX_P_LOG);
+ *cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
+ }
+ } else {
+ /* requested format not supported */
+ WARNINGA("format %d not supported\n", SKYPIAX_P_LOG, format);
+ *cause = AST_CAUSE_BEARERCAPABILITY_NOTAVAIL;
+ }
+ /* we found the requested interface, bail out from the while loop */
+ break;
+ }
+ /* not yet found, next please */
+ p = p->next;
+ }
+ /* unlock the interfaces' list */
+ UNLOCKA(&skypiax_iflock);
+ /* restart the monitor so it will watch only the remaining unowned interfaces */
+ skypiax_restart_monitor();
+ if (tmp == NULL) {
+ /* new channel was not created */
+ WARNINGA("Unable to create new Skypiax channel %s\n", SKYPIAX_P_LOG, name);
+ }
+ /* return the newly created channel */
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return tmp;
+}
+
+/*! \brief Hangup skypiax call
+ * Part of PBX interface, called from ast_hangup */
+
+int skypiax_hangup(struct ast_channel *c)
+{
+ struct skypiax_pvt *p;
+
+ /* get our skypiax pvt interface from channel */
+ p = c->tech_pvt;
+ /* if there is not skypiax pvt why we are here ? */
+ if (!p) {
+ ERRORA("Asked to hangup channel not connected\n", SKYPIAX_P_LOG);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return 0;
+ }
+
+ if (option_debug > 10) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+ if (p->skype && p->interface_state != AST_STATE_DOWN) {
+ char msg_to_skype[1024];
+ p->interface_state = AST_STATE_HANGUP_REQUESTED;
+ DEBUGA_SKYPE("hanging up skype call: %s\n", SKYPIAX_P_LOG, p->skype_call_id);
+ //sprintf(msg_to_skype, "SET CALL %s STATUS FINISHED", p->skype_call_id);
+ sprintf(msg_to_skype, "ALTER CALL %s HANGUP", p->skype_call_id);
+ skypiax_skype_write(p, msg_to_skype);
+ }
+
+ while (p->interface_state != AST_STATE_DOWN) {
+ usleep(10000);
+ }
+ DEBUGA_SKYPE("Now is really DOWN\n", SKYPIAX_P_LOG);
+ /* shutdown the serial monitoring thread */
+ if (p->controldev_thread && (p->controldev_thread != AST_PTHREADT_NULL)
+ && (p->controldev_thread != AST_PTHREADT_STOP)) {
+ if (pthread_cancel(p->controldev_thread)) {
+ ERRORA("controldev_thread pthread_cancel failed, maybe he killed himself?\n",
+ SKYPIAX_P_LOG);
+ }
+ /* push it, maybe is stuck in a select or so */
+ if (pthread_kill(p->controldev_thread, SIGURG)) {
+ DEBUGA_SERIAL("controldev_thread pthread_kill failed, no problem\n", SKYPIAX_P_LOG);
+ }
+#ifndef __CYGWIN__ /* under cygwin, this seems to be not reliable, get stuck at times */
+ /* wait for it to die */
+ if (pthread_join(p->controldev_thread, NULL)) {
+ ERRORA("controldev_thread pthread_join failed, BAD\n", SKYPIAX_P_LOG);
+ }
+#else /* __CYGWIN__ */
+/* allow the serial thread to die */
+ usleep(300000); //300msecs
+#endif /* __CYGWIN__ */
+ }
+ p->controldev_thread = AST_PTHREADT_NULL;
+
+ p->interface_state = AST_STATE_DOWN;
+ p->skype_callflow = CALLFLOW_CALL_IDLE;
+
+ DEBUGA_PBX("I'll send AST_CONTROL_HANGUP\n", SKYPIAX_P_LOG);
+ ast_queue_control(p->owner, AST_CONTROL_HANGUP);
+ DEBUGA_PBX("I've sent AST_CONTROL_HANGUP\n", SKYPIAX_P_LOG);
+
+ /* subtract one to the usage count of Skypiax-type channels */
+ LOKKA(&skypiax_usecnt_lock);
+ skypiax_usecnt--;
+ if (skypiax_usecnt < 0)
+ ERRORA("Usecnt < 0???\n", SKYPIAX_P_LOG);
+ UNLOCKA(&skypiax_usecnt_lock);
+ ast_update_use_count();
+
+ /* our skypiax pvt interface is no more part of a channel */
+ p->owner = NULL;
+ /* our channel has no more this skypiax pvt interface to manage */
+ c->tech_pvt = NULL;
+ /* set the channel state to DOWN, eg. available, not in active use */
+ if (ast_setstate(c, AST_STATE_DOWN)) {
+ ERRORA("ast_setstate failed, BAD\n", SKYPIAX_P_LOG);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return -1;
+ }
+
+ if (option_debug)
+ DEBUGA_PBX("Hanged Up\n", SKYPIAX_P_LOG);
+ /* restart the monitor thread, so it can recheck which interfaces it have to watch during its loop (the interfaces that are not owned by channels) */
+ if (skypiax_restart_monitor()) {
+ ERRORA("skypiax_restart_monitor failed, BAD\n", SKYPIAX_P_LOG);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return -1;
+ }
+
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return 0;
+}
+
+/*! \brief Answer incoming call,
+ * Part of PBX interface */
+int skypiax_answer(struct ast_channel *c)
+{
+ struct skypiax_pvt *p = c->tech_pvt;
+ int res;
+
+ if (option_debug > 10) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+ /* whle ringing, we just wait, the skype thread will answer */
+ while (p->interface_state == AST_STATE_RING) {
+ usleep(10000); //10msec
+ }
+ if (p->interface_state != AST_STATE_UP) {
+ ERRORA("call answering failed\n", SKYPIAX_P_LOG);
+ res = -1;
+ } else {
+ if (option_debug)
+ DEBUGA_PBX("call answered\n", SKYPIAX_P_LOG);
+ res = 0;
+ }
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return res;
+}
+
+#ifdef ASTERISK_VERSION_1_4
+int skypiax_senddigit_begin(struct ast_channel *c, char digit)
+{
+ struct skypiax_pvt *p = c->tech_pvt;
+ if (option_debug > 10) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+
+ DEBUGA_PBX("DIGIT BEGIN received: %c\n", SKYPIAX_P_LOG, digit);
+
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return 0;
+}
+
+int skypiax_senddigit_end(struct ast_channel *c, char digit, unsigned int duration)
+{
+ struct skypiax_pvt *p = c->tech_pvt;
+ char msg_to_skype[1024];
+ if (option_debug > 10) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+
+ NOTICA("DIGIT END received: %c %d\n", SKYPIAX_P_LOG, digit, duration);
+
+ sprintf(msg_to_skype, "SET CALL %s DTMF %c", p->skype_call_id, digit);
+
+ skypiax_skype_write(p, msg_to_skype);
+
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return 0;
+}
+#else /* ASTERISK_VERSION_1_4 */
+int skypiax_senddigit(struct ast_channel *c, char digit)
+{
+ struct skypiax_pvt *p = c->tech_pvt;
+ char msg_to_skype[1024];
+
+ if (option_debug > 10) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+ NOTICA("DIGIT received: %c\n", SKYPIAX_P_LOG, digit);
+
+ sprintf(msg_to_skype, "SET CALL %s DTMF %c", p->skype_call_id, digit);
+
+ skypiax_skype_write(p, msg_to_skype);
+
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return 0;
+}
+
+#endif /* ASTERISK_VERSION_1_4 */
+//struct ast_frame *skypiax_skypeaudio_read(struct skypiax_pvt *p)
+#define SAMPLES_PER_FRAME 160
+/*! \brief Read audio frames from channel */
+struct ast_frame *skypiax_read(struct ast_channel *c)
+{
+ struct skypiax_pvt *p = c->tech_pvt;
+ static struct ast_frame f;
+ static short __buf[SKYPIAX_FRAME_SIZE + AST_FRIENDLY_OFFSET / 2];
+ short *buf;
+ int samples;
+
+ if (option_debug > 100) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+
+/* if there are control frames queued to be sent by skypiax_queue_control, send it the first */
+//TODO maybe better a real queue?
+ if (p && p->owner && p->control_to_send) {
+ ast_queue_control(p->owner, p->control_to_send);
+ DEBUGA_PBX("Sent CONTROL FRAME %d\n", SKYPIAX_P_LOG, p->control_to_send);
+ p->control_to_send = 0;
+ }
+
+ memset(__buf, '\0', (SKYPIAX_FRAME_SIZE + AST_FRIENDLY_OFFSET / 2));
+
+ buf = __buf + AST_FRIENDLY_OFFSET / 2;
+
+ f.frametype = AST_FRAME_NULL;
+ f.subclass = 0;
+ f.samples = 0;
+ f.datalen = 0;
+ f.data = NULL;
+ f.offset = 0;
+ f.src = skypiax_type;
+ f.mallocd = 0;
+ f.delivery.tv_sec = 0;
+ f.delivery.tv_usec = 0;
+
+/* if the call is not active (ie: answered), do not send audio frames, they would pile up in a lag queue */
+ if (p->owner && p->owner->_state != AST_STATE_UP) {
+ if (option_debug > 100) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return &f;
+ }
+
+ if ((samples = read(p->audiopipe[0], buf, SAMPLES_PER_FRAME * sizeof(short))) != 320) {
+ DEBUGA_SOUND("read=====> NOT GOOD samples=%d expected=%d\n", SKYPIAX_P_LOG, samples,
+ SAMPLES_PER_FRAME * sizeof(short));
+ usleep(100);
+ //do nothing
+ } else {
+ //DEBUGA_SOUND("read=====> GOOD samples=%d\n", SKYPIAX_P_LOG, samples);
+ /* A real frame */
+ f.frametype = AST_FRAME_VOICE;
+ f.subclass = AST_FORMAT_SLINEAR;
+ f.samples = SKYPIAX_FRAME_SIZE;
+ f.datalen = SKYPIAX_FRAME_SIZE * 2;
+ f.data = buf;
+ f.offset = AST_FRIENDLY_OFFSET;
+ f.src = skypiax_type;
+ f.mallocd = 0;
+
+ if (p->capture_boost)
+ skypiax_sound_boost(&f, p->capture_boost);
+ }
+
+ if (option_debug > 100) {
+ DEBUGA_SOUND("samples=%d\n", SKYPIAX_P_LOG, samples);
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return &f;
+}
+
+/*! \brief Initiate skypiax call from PBX
+ * used from the dial() application
+ */
+int skypiax_call(struct ast_channel *c, char *idest, int timeout)
+{
+ struct skypiax_pvt *p = NULL;
+ p = c->tech_pvt;
+ char rdest[80], *where, dstr[100] = "";
+ char *stringp = NULL;
+ int status;
+
+ if (option_debug > 10) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+ if ((c->_state != AST_STATE_DOWN)
+ && (c->_state != AST_STATE_RESERVED)) {
+ ERRORA("skypiax_call called on %s, neither down nor reserved\n", SKYPIAX_P_LOG,
+ c->name);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return -1;
+ }
+
+ if (option_debug > 1)
+ DEBUGA_PBX("skypiax_call to call idest: %s, timeout: %d!\n", SKYPIAX_P_LOG, idest,
+ timeout);
+
+ strncpy(rdest, idest, sizeof(rdest) - 1);
+ stringp = rdest;
+ strsep(&stringp, "/");
+ where = strsep(&stringp, "/");
+ if (!where) {
+ ERRORA("Destination %s requires an actual destination (Skypiax/device/destination)\n",
+ SKYPIAX_P_LOG, idest);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return -1;
+ }
+
+ strncpy(dstr, where + p->stripmsd, sizeof(dstr) - 1);
+ if (option_debug > 1)
+ DEBUGA_PBX("skypiax_call dialing idest: %s, timeout: %d, dstr: %s!\n", SKYPIAX_P_LOG,
+ idest, timeout, dstr);
+
+ status = skypiax_skype_call(p, dstr, timeout);
+ if (status) {
+ WARNINGA("skypiax_call dialing failed: %d!\n", SKYPIAX_P_LOG, status);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return -1;
+ }
+
+ if (option_debug > 1)
+ DEBUGA_PBX("skypiax_call dialed idest: %s, timeout: %d, dstr: %s!\n", SKYPIAX_P_LOG,
+ idest, timeout, dstr);
+
+ ast_setstate(p->owner, AST_STATE_DIALING);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return 0;
+}
+
+int skypiax_sound_boost(struct ast_frame *f, double boost)
+{
+/* LUIGI RIZZO's magic */
+ if (boost != 0) { /* scale and clip values */
+ int i, x;
+ int16_t *ptr = (int16_t *) f->data;
+ for (i = 0; i < f->samples; i++) {
+ x = (ptr[i] * boost) / BOOST_SCALE;
+ if (x > 32767) {
+ x = 32767;
+ } else if (x < -32768) {
+ x = -32768;
+ }
+ ptr[i] = x;
+ }
+ }
+ return 0;
+}
+
+/*! \brief Send audio frame to channel */
+int skypiax_write(struct ast_channel *c, struct ast_frame *f)
+{
+ struct skypiax_pvt *p = c->tech_pvt;
+ int sent;
+
+ if (option_debug > 100) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+ if (p->owner && p->owner->_state != AST_STATE_UP) {
+ if (option_debug > 100) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return 0;
+ }
+ if (p->playback_boost)
+ skypiax_sound_boost(f, p->playback_boost);
+
+ sent = write(p->audioskypepipe[1], (short *) f->data, f->datalen);
+ //skypiax_sound_write(p, f);
+
+ if (option_debug > 100) {
+ DEBUGA_SOUND("sent=%d\n", SKYPIAX_P_LOG, sent);
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return 0;
+}
+
+/*! \brief Fix up a channel: If a channel is consumed, this is called.
+ * Basically update any ->owner links */
+int skypiax_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
+{
+ struct skypiax_pvt *p = newchan->tech_pvt;
+
+ if (option_debug > 10) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+ if (!p) {
+ ERRORA("No pvt after masquerade. Strange things may happen\n", SKYPIAX_P_LOG);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return -1;
+ }
+
+ if (p->owner != oldchan) {
+ ERRORA("old channel wasn't %p but was %p\n", SKYPIAX_P_LOG, oldchan, p->owner);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return -1;
+ }
+
+ p->owner = newchan;
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return 0;
+}
+
+struct ast_channel *skypiax_new(struct skypiax_pvt *p, int state, char *context)
+{
+ struct ast_channel *tmp;
+
+ if (option_debug > 10) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+ /* alloc a generic channel struct */
+#ifndef ASTERISK_VERSION_1_4
+ tmp = ast_channel_alloc(1);
+#else
+ //tmp = ast_channel_alloc(1, state, 0, 0, "", p->exten, p->context, 0, "");
+ //tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "Skypiax/%s", p->name);
+ tmp =
+ ast_channel_alloc(1, state, 0, 0, "", p->exten, p->context, 0, "Skypiax/%s", p->name);
+
+#endif /* ASTERISK_VERSION_1_4 */
+ if (tmp) {
+
+ /* give a name to the newly created channel */
+#ifndef ASTERISK_VERSION_1_4
+ snprintf(tmp->name, sizeof(tmp->name), "Skypiax/%s", p->name);
+ tmp->type = skypiax_type;
+#else /* ASTERISK_VERSION_1_4 */
+ ast_string_field_build(tmp, name, "Skypiax/%s", p->name);
+#endif /* ASTERISK_VERSION_1_4 */
+
+ DEBUGA_PBX("new channel: name=%s requested_state=%d\n", SKYPIAX_P_LOG, tmp->name,
+ state);
+
+ /* fd for the channel to poll for incoming audio */
+ tmp->fds[0] = p->skypiax_sound_capt_fd;
+
+ /* audio formats managed */
+ tmp->nativeformats = AST_FORMAT_SLINEAR;
+ tmp->readformat = AST_FORMAT_SLINEAR;
+ tmp->writeformat = AST_FORMAT_SLINEAR;
+ /* the technology description (eg. the interface type) of the newly created channel is the Skypiax's one */
+ tmp->tech = &skypiax_tech;
+ /* the technology pvt (eg. the interface) of the newly created channel is this interface pvt */
+ tmp->tech_pvt = p;
+
+ /* copy this interface default context, extension, language to the newly created channel */
+ if (strlen(p->context))
+ strncpy(tmp->context, p->context, sizeof(tmp->context) - 1);
+ if (strlen(p->exten))
+ strncpy(tmp->exten, p->exten, sizeof(tmp->exten) - 1);
+#ifndef ASTERISK_VERSION_1_4
+ if (strlen(p->language))
+ strncpy(tmp->language, p->language, sizeof(tmp->language) - 1);
+#else
+ if (strlen(p->language))
+ ast_string_field_set(tmp, language, p->language);
+#endif /* ASTERISK_VERSION_1_4 */
+ /* copy the requested context (not necessarily the interface default) to the newly created channel */
+ if (strlen(context))
+ strncpy(tmp->context, context, sizeof(tmp->context) - 1);
+
+ /* copy this interface default callerid in the newly created channel */
+ ast_set_callerid(tmp, !ast_strlen_zero(p->callid_number) ? p->callid_number : NULL,
+ !ast_strlen_zero(p->callid_name) ? p->callid_name : NULL,
+ !ast_strlen_zero(p->callid_number) ? p->callid_number : NULL);
+
+ DEBUGA_PBX("callid_number=%s, callid_name=%s\n", SKYPIAX_P_LOG, p->callid_number,
+ p->callid_name);
+
+ /* the owner of this interface pvt is the newly created channel */
+ p->owner = tmp;
+ /* set the newly created channel state to the requested state */
+ if (ast_setstate(tmp, state)) {
+ ERRORA("ast_setstate failed, BAD\n", SKYPIAX_P_LOG);
+ //ast_dsp_free(p->dsp);
+ ast_channel_free(tmp);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return NULL;
+ }
+ /* if the requested state is different from DOWN, let the pbx manage this interface (now part of the newly created channel) */
+ if (state != AST_STATE_DOWN) {
+ DEBUGA_PBX("Try to start PBX on %s, state=%d\n", SKYPIAX_P_LOG, tmp->name, state);
+ if (ast_pbx_start(tmp)) {
+ ERRORA("Unable to start PBX on %s\n", SKYPIAX_P_LOG, tmp->name);
+ ast_channel_free(tmp);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return NULL;
+ }
+ }
+ /* let's start the serial monitoring thread too, so we can have serial signaling */
+ if (ast_pthread_create(&p->controldev_thread, NULL, skypiax_do_controldev_thread, p) <
+ 0) {
+ ERRORA("Unable to start controldev thread.\n", SKYPIAX_P_LOG);
+ ast_channel_free(tmp);
+ tmp = NULL;
+ }
+ DEBUGA_SERIAL("STARTED controldev_thread=%lu STOP=%lu NULL=%lu\n", SKYPIAX_P_LOG,
+ (unsigned long) p->controldev_thread, (unsigned long) AST_PTHREADT_STOP,
+ (unsigned long) AST_PTHREADT_NULL);
+
+ /* add one to the usage count of Skypiax-type channels */
+ LOKKA(&skypiax_usecnt_lock);
+ skypiax_usecnt++;
+ UNLOCKA(&skypiax_usecnt_lock);
+ ast_update_use_count();
+
+ /* return the newly created channel */
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return tmp;
+ }
+ ERRORA("failed memory allocation for Skypiax channel\n", SKYPIAX_P_LOG);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return NULL;
+}
+
+/*!
+ * \brief Load the module into Asterisk and start its threads
+ *
+ * This function register the module into Asterisk,
+ * create the interfaces for the channels,
+ * start the auxiliary threads for the interfaces,
+ * then start a monitor thread. The monitor thread
+ * will signal Asterisk when an interface receive a call.
+ *
+ *
+ * \return zero on success, -1 on error.
+ */
+int load_module(void)
+{
+ int i;
+ struct ast_config *cfg;
+ struct skypiax_pvt *tmp;
+ struct skypiax_pvt *p = NULL;
+#ifdef ASTERISK_VERSION_1_6
+ struct ast_flags config_flags = { 0 };
+#endif /* ASTERISK_VERSION_1_6 */
+
+ if (option_debug > 10) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ ast_log(LOG_DEBUG, "ENTERING FUNC\n");
+ }
+#if defined(WANT_SKYPE_X11) || defined(__CYGWIN__)
+#ifndef __CYGWIN__
+ if (!XInitThreads())
+ ast_log(LOG_ERROR, "Not initialized XInitThreads!\n");
+#endif /* __CYGWIN__ */
+#if 0
+ ast_register_atexit(skypiax_skype_disconnect);
+ ast_register_application(skype2skypiaxapp, skype2skypiax, skype2skypiaxsynopsis,
+ skype2skypiaxdescrip);
+ ast_register_application(skypiax2skypeapp, skypiax2skype, skypiax2skypesynopsis,
+ skypiax2skypedescrip);
+#endif
+#endif /* defined(WANT_SKYPE_X11) || defined(__CYGWIN__) */
+
+ /* make sure we can register our channel type with Asterisk */
+ i = ast_channel_register(&skypiax_tech);
+ if (i < 0) {
+ ERRORA("Unable to register channel type '%s'\n", SKYPIAX_P_LOG, skypiax_type);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return -1;
+ }
+ /* load skypiax.conf config file */
+#ifdef ASTERISK_VERSION_1_6
+ cfg = ast_config_load(skypiax_config, config_flags);
+#else
+ cfg = ast_config_load(skypiax_config);
+#endif /* ASTERISK_VERSION_1_6 */
+ if (cfg != NULL) {
+ char *ctg = NULL;
+ int is_first_category = 1;
+ while ((ctg = ast_category_browse(cfg, ctg)) != NULL) {
+ /* create one interface for each category in skypiax.conf config file, first one set the defaults */
+ tmp = skypiax_mkif(cfg, ctg, is_first_category);
+ if (tmp) {
+ DEBUGA_PBX
+ ("Created channel Skypiax: skypiax.conf category '[%s]', channel name '%s'"
+ "\n", SKYPIAX_P_LOG, ctg, tmp->name);
+ /* add interface to skypiax_iflist */
+ tmp->next = skypiax_iflist;
+ skypiax_iflist = tmp;
+ /* next one will not be the first ;) */
+ if (is_first_category == 1) {
+ is_first_category = 0;
+ skypiax_console_active = tmp->name;
+ }
+ } else {
+ ERRORA("Unable to create channel Skypiax from skypiax.conf category '[%s]'\n",
+ SKYPIAX_P_LOG, ctg);
+ /* if error, unload config from memory and return */
+ ast_config_destroy(cfg);
+ ast_channel_unregister(&skypiax_tech);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return -1;
+ }
+ /* do it for each category described in config */
+ }
+
+ /* we finished, unload config from memory */
+ ast_config_destroy(cfg);
+ } else {
+ ERRORA("Unable to load skypiax_config skypiax.conf\n", SKYPIAX_P_LOG);
+ ast_channel_unregister(&skypiax_tech);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return -1;
+ }
+#ifndef ASTERISK_VERSION_1_6
+ ast_cli_register_multiple(myclis, sizeof(myclis) / sizeof(struct ast_cli_entry));
+#endif /* ASTERISK_VERSION_1_6 */
+ /* start to monitor the interfaces (skypiax_iflist) for the first time */
+ if (skypiax_restart_monitor()) {
+ ERRORA("skypiax_restart_monitor failed, BAD\n", SKYPIAX_P_LOG);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return -1;
+ }
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return 0;
+}
+
+/*!
+ * \brief Unload the module from Asterisk and shutdown its threads
+ *
+ * This function unregister the module from Asterisk,
+ * destroy the interfaces for the channels,
+ * shutdown the auxiliary threads for the interfaces,
+ * then shutdown its monitor thread.
+ *
+ * \return zero on success, -1 on error.
+ */
+int unload_module(void)
+{
+ struct skypiax_pvt *p = NULL, *p2 = NULL;
+ int res;
+
+ if (option_debug > 10) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+
+ /* unregister our channel type with Asterisk */
+ ast_channel_unregister(&skypiax_tech);
+ ast_cli_unregister_multiple(myclis, sizeof(myclis) / sizeof(struct ast_cli_entry));
+
+#if defined(WANT_SKYPE_X11) || defined(__CYGWIN__)
+#ifndef __CYGWIN__
+ //FIXME what to do? if (!XInitThreads())
+ //FIXME what to do? ast_log(LOG_ERROR, "Not initialized XInitThreads!\n");
+#endif /* __CYGWIN__ */
+#if 0
+ ast_unregister_atexit(skypiax_skype_disconnect);
+ ast_unregister_application(skype2skypiaxapp);
+ ast_unregister_application(skypiax2skypeapp);
+#endif
+#endif /* defined(WANT_SKYPE_X11) || defined(__CYGWIN__) */
+
+ /* lock the skypiax_monlock, kill the monitor thread, unlock the skypiax_monlock */
+ LOKKA(&skypiax_monlock);
+ if (skypiax_monitor_thread && (skypiax_monitor_thread != AST_PTHREADT_NULL)
+ && (skypiax_monitor_thread != AST_PTHREADT_STOP)) {
+ if (pthread_cancel(skypiax_monitor_thread)) {
+ ERRORA("pthread_cancel failed, BAD\n", SKYPIAX_P_LOG);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return -1;
+ }
+ if (pthread_kill(skypiax_monitor_thread, SIGURG)) {
+ DEBUGA_PBX("pthread_kill failed\n", SKYPIAX_P_LOG); //maybe it just died
+ }
+#ifndef __CYGWIN__ /* under cygwin, this seems to be not reliable, get stuck at times */
+ if (pthread_join(skypiax_monitor_thread, NULL)) {
+ ERRORA("pthread_join failed, BAD\n", SKYPIAX_P_LOG);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return -1;
+ }
+#endif /* __CYGWIN__ */
+ }
+ skypiax_monitor_thread = AST_PTHREADT_STOP;
+ UNLOCKA(&skypiax_monlock);
+
+ if (skypiax_monitor_audio_thread && (skypiax_monitor_audio_thread != AST_PTHREADT_NULL)
+ && (skypiax_monitor_audio_thread != AST_PTHREADT_STOP)) {
+
+ if (pthread_cancel(skypiax_monitor_audio_thread)) {
+ ERRORA("pthread_cancel skypiax_monitor_audio_thread failed, BAD\n", SKYPIAX_P_LOG);
+ }
+ if (pthread_kill(skypiax_monitor_audio_thread, SIGURG)) {
+ DEBUGA_PBX("pthread_kill skypiax_monitor_audio_thread failed, no problem\n", SKYPIAX_P_LOG); //maybe it just died
+ }
+
+ if (pthread_join(skypiax_monitor_audio_thread, NULL)) {
+ ERRORA("pthread_join failed, BAD\n", SKYPIAX_P_LOG);
+ }
+ }
+ /* lock the skypiax_iflock, and go through the interfaces list (skypiax_iflist) */
+ LOKKA(&skypiax_iflock);
+ p = skypiax_iflist;
+ while (p) {
+ /* for each interface in list */
+ p2 = p->next;
+ /* shutdown the sound system, close sound fds, and if exist shutdown the sound managing threads */
+ DEBUGA_SOUND("shutting down sound\n", SKYPIAX_P_LOG);
+ res = skypiax_sound_shutdown(p);
+ if (res == -1) {
+ ERRORA("Failed to shutdown sound\n", SKYPIAX_P_LOG);
+ }
+#if 0
+ /* if a dsp struct has been allocated, free it */
+ if (p->dsp) {
+ ast_dsp_free(p->dsp);
+ p->dsp = NULL;
+ }
+#endif
+ DEBUGA_PBX("freeing PVT\n", SKYPIAX_P_LOG);
+ /* free the pvt allocated memory */
+ free(p);
+ /* next one, please */
+ p = p2;
+ }
+ /* finished with the interfaces list, unlock the skypiax_iflock */
+ UNLOCKA(&skypiax_iflock);
+
+#ifdef __CYGWIN__
+ NOTICA("Sleping 5 secs, please wait...\n", SKYPIAX_P_LOG);
+ sleep(5); /* without this pause, for some unknown (to me) reason it crashes on cygwin */
+#endif /* __CYGWIN__ */
+ NOTICA("Unloaded Skypiax Module\n", SKYPIAX_P_LOG);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return 0;
+}
+
+/*!
+ * \brief Return the count of active channels for this module
+ *
+ * \return the count of active channels for this module
+ */
+int usecount()
+{
+ int res;
+ static struct skypiax_pvt *p = &skypiax_log_struct;
+ if (option_debug > 10) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+/* lock the skypiax_usecnt lock */
+ LOKKA(&skypiax_usecnt_lock);
+ /* retrieve the skypiax_usecnt */
+ res = skypiax_usecnt;
+/* unlock the skypiax_usecnt lock */
+ UNLOCKA(&skypiax_usecnt_lock);
+ /* return the skypiax_usecnt */
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return res;
+}
+
+/*!
+ * \brief Return the textual description of the module
+ *
+ * \return the textual description of the module
+ */
+char *description()
+{
+ static struct skypiax_pvt *p = &skypiax_log_struct;
+ if (option_debug > 10) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return (char *) skypiax_desc;
+}
+
+/*!
+ * \brief Return the ASTERISK_GPL_KEY
+ *
+ * \return the ASTERISK_GPL_KEY
+ */
+char *key()
+{
+ struct skypiax_pvt *p = NULL;
+ if (option_debug > 10) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+
+ if (option_debug)
+ NOTICA("Returning Key\n", SKYPIAX_P_LOG);
+
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return ASTERISK_GPL_KEY;
+}
+
+/*!
+ * \brief Create and initialize one interface for the module
+ * \param cfg pointer to configuration data from skypiax.conf
+ * \param ctg pointer to a category name to be found in cfg
+ * \param is_first_category is this the first category in cfg
+ *
+ * This function create and initialize one interface for the module
+ *
+ * \return a pointer to the PVT structure of interface on success, NULL on error.
+ */
+struct skypiax_pvt *skypiax_mkif(struct ast_config *cfg, char *ctg, int is_first_category)
+{
+ struct skypiax_pvt *tmp;
+ struct ast_variable *v;
+ int res;
+
+ int debug_all = 0;
+ int debug_at = 0;
+ int debug_fbus2 = 0;
+ int debug_serial = 0;
+ int debug_sound = 0;
+ int debug_pbx = 0;
+ int debug_skype = 0;
+ int debug_call = 0;
+ int debug_locks = 0;
+ int debug_monitorlocks = 0;
+
+ ast_log(LOG_DEBUG, "ENTERING FUNC\n");
+ /* alloc memory for PVT */
+ tmp = malloc(sizeof(struct skypiax_pvt));
+ if (tmp == NULL) { /* fail */
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_TMP_LOG);
+ ast_log(LOG_DEBUG, "EXITING FUNC\n");
+ }
+ return NULL;
+ }
+ /* clear memory for PVT */
+ memset(tmp, 0, sizeof(struct skypiax_pvt));
+
+ /* if we are reading the "first" category of the config file, take SELECTED values as defaults, overriding the values in skypiax_default */
+ if (is_first_category == 1) {
+ /* for each variable in category, copy it in the skypiax_default struct */
+ for (v = ast_variable_browse(cfg, ctg); v; v = v->next) {
+ M_START(v->name, v->value);
+
+ M_STR("context", skypiax_default.context)
+ M_STR("language", skypiax_default.language)
+ M_STR("extension", skypiax_default.exten)
+ M_F("playback_boost",
+ skypiax_store_boost(v->value, &skypiax_default.playback_boost))
+ M_F("capture_boost",
+ skypiax_store_boost(v->value, &skypiax_default.capture_boost))
+ M_UINT("skypiax_dir_entry_extension_prefix",
+ skypiax_default.skypiax_dir_entry_extension_prefix)
+ M_END(;);
+ }
+ }
+
+ /* initialize the newly created PVT from the skypiax_default values */
+ *tmp = skypiax_default;
+
+ /* the category name becomes the interface name */
+ tmp->name = strdup(ctg);
+
+ /* for each category in config file, "first" included, read in ALL the values */
+ for (v = ast_variable_browse(cfg, ctg); v; v = v->next) {
+ M_START(v->name, v->value);
+
+ M_BOOL("debug_all", debug_all)
+ M_BOOL("debug_at", debug_at)
+ M_BOOL("debug_fbus2", debug_fbus2)
+ M_BOOL("debug_serial", debug_serial)
+ M_BOOL("debug_sound", debug_sound)
+ M_BOOL("debug_pbx", debug_pbx)
+ M_BOOL("debug_skype", debug_skype)
+ M_BOOL("debug_call", debug_call)
+ M_BOOL("debug_locks", debug_locks)
+ M_BOOL("debug_monitorlocks", debug_monitorlocks)
+ M_BOOL("skype", tmp->skype)
+ M_STR("context", tmp->context)
+ M_STR("language", tmp->language)
+ M_STR("extension", tmp->exten)
+ M_F("playback_boost", skypiax_store_boost(v->value, &tmp->playback_boost))
+ M_F("capture_boost", skypiax_store_boost(v->value, &tmp->capture_boost))
+ M_UINT("skypiax_dir_entry_extension_prefix",
+ tmp->skypiax_dir_entry_extension_prefix)
+ M_END(;);
+ }
+
+ if (debug_all) {
+ skypiax_debug = skypiax_debug | DEBUG_ALL;
+ if (!option_debug) {
+ WARNINGA
+ ("DEBUG_ALL activated, but option_debug is 0. You have to set debug level higher than zero to see some debugging output. Please use the command \"set debug 10\" or start Asterisk with \"-dddddddddd\" option for full DEBUG_ALL debugging output.\n",
+ SKYPIAX_TMP_LOG);
+ } else {
+ NOTICA("DEBUG_ALL activated. \n", SKYPIAX_TMP_LOG);
+ }
+ }
+
+ if (debug_fbus2) {
+ skypiax_debug = skypiax_debug | DEBUG_FBUS2;
+ if (!option_debug) {
+ WARNINGA
+ ("DEBUG_FBUS2 activated, but option_debug is 0. You have to set debug level higher than zero to see some debugging output. Please use the command \"set debug 10\" or start Asterisk with \"-dddddddddd\" option for full DEBUG_FBUS2 debugging output.\n",
+ SKYPIAX_TMP_LOG);
+ } else {
+ NOTICA("DEBUG_FBUS2 activated. \n", SKYPIAX_TMP_LOG);
+ }
+ }
-#include <switch.h>
+ if (debug_serial) {
+ skypiax_debug = skypiax_debug | DEBUG_SERIAL;
+ if (!option_debug) {
+ WARNINGA
+ ("DEBUG_SERIAL activated, but option_debug is 0. You have to set debug level higher than zero to see some debugging output. Please use the command \"set debug 10\" or start Asterisk with \"-dddddddddd\" option for full DEBUG_SERIAL debugging output.\n",
+ SKYPIAX_TMP_LOG);
+ } else {
+ NOTICA("DEBUG_SERIAL activated. \n", SKYPIAX_TMP_LOG);
+ }
+ }
+
+ if (debug_sound) {
+ skypiax_debug = skypiax_debug | DEBUG_SOUND;
+ if (!option_debug) {
+ WARNINGA
+ ("DEBUG_SOUND activated, but option_debug is 0. You have to set debug level higher than zero to see some debugging output. Please use the command \"set debug 10\" or start Asterisk with \"-dddddddddd\" option for full DEBUG_SOUND debugging output.\n",
+ SKYPIAX_TMP_LOG);
+ } else {
+ NOTICA("DEBUG_SOUND activated. \n", SKYPIAX_TMP_LOG);
+ }
+ }
+
+ if (debug_pbx) {
+ skypiax_debug = skypiax_debug | DEBUG_PBX;
+ if (!option_debug) {
+ WARNINGA
+ ("DEBUG_PBX activated, but option_debug is 0. You have to set debug level higher than zero to see some debugging output. Please use the command \"set debug 10\" or start Asterisk with \"-dddddddddd\" option for full DEBUG_PBX debugging output.\n",
+ SKYPIAX_TMP_LOG);
+ } else {
+ NOTICA("DEBUG_PBX activated. \n", SKYPIAX_TMP_LOG);
+ }
+ }
+
+ if (debug_skype) {
+ skypiax_debug = skypiax_debug | DEBUG_SKYPE;
+ if (!option_debug) {
+ WARNINGA
+ ("DEBUG_SKYPE activated, but option_debug is 0. You have to set debug level higher than zero to see some debugging output. Please use the command \"set debug 10\" or start Asterisk with \"-dddddddddd\" option for full DEBUG_SKYPE debugging output.\n",
+ SKYPIAX_TMP_LOG);
+ } else {
+ NOTICA("DEBUG_SKYPE activated. \n", SKYPIAX_TMP_LOG);
+ }
+ }
+
+ if (debug_call) {
+ skypiax_debug = skypiax_debug | DEBUG_CALL;
+ if (!option_debug) {
+ WARNINGA
+ ("DEBUG_CALL activated, but option_debug is 0. You have to set debug level higher than zero to see some debugging output. Please use the command \"set debug 10\" or start Asterisk with \"-dddddddddd\" option for full DEBUG_CALL debugging output.\n",
+ SKYPIAX_TMP_LOG);
+ } else {
+ NOTICA("DEBUG_CALL activated. \n", SKYPIAX_TMP_LOG);
+ }
+ }
+
+ if (debug_locks) {
+ skypiax_debug = skypiax_debug | DEBUG_LOCKS;
+ if (!option_debug) {
+ WARNINGA
+ ("DEBUG_LOCKS activated, but option_debug is 0. You have to set debug level higher than zero to see some debugging output. Please use the command \"set debug 10\" or start Asterisk with \"-dddddddddd\" option for full DEBUG_LOCKS debugging output.\n",
+ SKYPIAX_TMP_LOG);
+ } else {
+ NOTICA("DEBUG_LOCKS activated. \n", SKYPIAX_TMP_LOG);
+ }
+ }
+
+ if (debug_monitorlocks) {
+ skypiax_debug = skypiax_debug | DEBUG_MONITORLOCKS;
+ if (!option_debug) {
+ WARNINGA
+ ("DEBUG_MONITORLOCKS activated, but option_debug is 0. You have to set debug level higher than zero to see some debugging output. Please use the command \"set debug 10\" or start Asterisk with \"-dddddddddd\" option for full DEBUG_MONITORLOCKS debugging output.\n",
+ SKYPIAX_TMP_LOG);
+ } else {
+ NOTICA("DEBUG_MONITORLOCKS activated. \n", SKYPIAX_TMP_LOG);
+ }
+ }
+
+ if (option_debug > 1) {
+ DEBUGA_SOUND("playback_boost is %f\n", SKYPIAX_TMP_LOG, tmp->playback_boost);
+ DEBUGA_SOUND("capture_boost is %f\n", SKYPIAX_TMP_LOG, tmp->capture_boost);
+ }
+ /* if skype is true for this interface, let's check if another interface has skype true */
+ if (tmp->skype) {
+ struct skypiax_pvt *p = NULL, *p2 = NULL;
+ /* lock the skypiax_iflock, maybe unneeded */
+ LOKKA(&skypiax_iflock);
+ p = skypiax_iflist;
+ /* for each pvt in the interfaces list (skypiax_iflist) */
+ while (p) {
+ p2 = p->next;
+ /* if another interface has skype true */
+ if (p->skype) {
+ ERRORA
+ ("This interface (category '[%s]') has 'skype=yes' in config, but up in skypiax.conf config file the interface category '[%s]' has yet 'skype=yes'. Only one interface at time can support skype. I'm sure, I wrote it ;). Setting 'skype=no' for interface category '[%s] and continuing\n",
+ SKYPIAX_P_LOG, tmp->name, p->name, tmp->name);
+ /* set this interface's skype to false */
+ tmp->skype = 0;
+ }
+ /* next interface, please */
+ p = p2;
+ }
+ /* unlock the skypiax_iflock */
+ UNLOCKA(&skypiax_iflock);
+ }
+/* initialize the soundcard channels (input and output) used by this interface (a multichannel soundcard can be used by multiple interfaces), optionally starting the sound managing threads */
+ res = skypiax_sound_init(tmp);
+ if (res == -1) {
+ ERRORA("Failed initializing sound device\n", SKYPIAX_TMP_LOG);
+ /* we failed, free the PVT */
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_TMP_LOG);
+ }
+ free(tmp);
+ return NULL;
+ }
+ res = pipe(tmp->AsteriskHandlesAst.fdesc);
+ if (res) {
+ ast_log(LOG_ERROR, "Unable to create skype pipe\n");
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_TMP_LOG);
+ }
+ free(tmp);
+ return NULL;
+ }
+ fcntl(tmp->AsteriskHandlesAst.fdesc[0], F_SETFL, O_NONBLOCK);
+ fcntl(tmp->AsteriskHandlesAst.fdesc[1], F_SETFL, O_NONBLOCK);
+ tmp->skype_thread = AST_PTHREADT_NULL;
+ if (tmp->skype) {
+ if (option_debug > 1)
+ ast_log(LOG_DEBUG, "TO BE started skype_thread=%lu STOP=%lu NULL=%lu\n",
+ (unsigned long) tmp->skype_thread, (unsigned long) AST_PTHREADT_STOP,
+ (unsigned long) AST_PTHREADT_NULL);
+#ifdef __CYGWIN__
+ if (ast_pthread_create
+ (&tmp->skype_thread, NULL, do_skype_thread, &tmp->AsteriskHandlesAst) < 0) {
+ ast_log(LOG_ERROR, "Unable to start skype_main thread.\n");
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_TMP_LOG);
+ }
+ free(tmp);
+ return NULL;
+ }
+#else /* __CYGWIN__ */
+#ifdef WANT_SKYPE_X11
+ if (option_debug > 1)
+ ast_log(LOG_DEBUG, "AsteriskHandlesfd: %d\n", tmp->AsteriskHandlesAst.fdesc[1]);
+ if (ast_pthread_create(&tmp->skype_thread, NULL, do_skype_thread, tmp) < 0) {
+ ast_log(LOG_ERROR, "Unable to start skype_main thread.\n");
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_TMP_LOG);
+ }
+ free(tmp);
+ return NULL;
+ }
+#endif /* WANT_SKYPE_X11 */
+#endif /* __CYGWIN__ */
+ usleep(100000); //0.1 sec
+ if( tmp->skype_thread == AST_PTHREADT_NULL){
+ ast_log(LOG_ERROR, "Unable to start skype_main thread.\n");
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_TMP_LOG);
+ }
+ free(tmp);
+ return NULL;
+ }
+ if (option_debug > 1)
+ ast_log(LOG_DEBUG, "STARTED skype_thread=%lu STOP=%lu NULL=%lu\n",
+ (unsigned long) tmp->skype_thread, (unsigned long) AST_PTHREADT_STOP,
+ (unsigned long) AST_PTHREADT_NULL);
+ }
+
+ /* return the newly created skypiax_pvt */
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_TMP_LOG);
+ }
+ return tmp;
+}
+
+/*! \brief (Re)Start the module main monitor thread, watching for incoming calls on the interfaces */
+int skypiax_restart_monitor(void)
+{
+ static struct skypiax_pvt *p = &skypiax_log_struct;
+
+ if (option_debug > 10) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+ /* If we're supposed to be stopped -- stay stopped */
+ if (skypiax_monitor_thread == AST_PTHREADT_STOP) {
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return 0;
+ }
+ LOKKA(&skypiax_monlock);
+ /* Do not seems possible to me that this function can be called by the very same monitor thread, but let's be paranoid */
+ if (skypiax_monitor_thread == pthread_self()) {
+ UNLOCKA(&skypiax_monlock);
+ ERRORA("Cannot kill myself\n", SKYPIAX_P_LOG);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return -1;
+ }
+ /* if the monitor thread exists */
+ if (skypiax_monitor_thread != AST_PTHREADT_NULL) {
+ /* Wake up the thread, it can be stuck waiting in a select or so */
+ pthread_kill(skypiax_monitor_thread, SIGURG);
+ } else {
+ /* the monitor thread does not exists, start a new monitor */
+ if (ast_pthread_create(&skypiax_monitor_thread, NULL, skypiax_do_monitor, NULL) < 0) {
+ UNLOCKA(&skypiax_monlock);
+ ERRORA("Unable to start monitor thread.\n", SKYPIAX_P_LOG);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return -1;
+ }
+ }
+ UNLOCKA(&skypiax_monlock);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return 0;
+}
+
+/*! \brief The skypiax monitoring thread
+ * \note This thread monitors all the skypiax interfaces that are not in a call
+ * (and thus do not have a separate thread) indefinitely
+ * */
+void *skypiax_do_monitor(void *data)
+{
+ fd_set rfds;
+ int res;
+ struct skypiax_pvt *p = NULL;
+ int max = -1;
+ struct timeval to;
+ time_t now_timestamp;
+
+ if (option_debug > 10) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+ if (pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL)) {
+ ERRORA("Unable to set cancel type to deferred\n", SKYPIAX_P_LOG);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return NULL;
+ }
-SWITCH_MODULE_LOAD_FUNCTION(mod_skypiax_load);
-SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_skypiax_shutdown);
-//SWITCH_MODULE_RUNTIME_FUNCTION(mod_skypiax_runtime);
-SWITCH_MODULE_DEFINITION(mod_skypiax, mod_skypiax_load, mod_skypiax_shutdown, NULL); //mod_skypiax_runtime);
+ for (;;) {
+ pthread_testcancel();
+ /* Don't let anybody kill us right away. Nobody should lock the interface list
+ and wait for the monitor list, but the other way around is okay. */
+ PUSHA_UNLOCKA(&skypiax_monlock);
+ MONITORLOKKA(&skypiax_monlock);
+ /* Lock the interface list */
+ PUSHA_UNLOCKA(&skypiax_iflock);
+ MONITORLOKKA(&skypiax_iflock);
+ /* Build the stuff we're going to select on, that is the skypiax_serial_fd of every
+ skypiax_pvt that does not have an associated owner channel. In the case of FBUS2 3310
+ and in the case of PROTOCOL_NO_SERIAL we add the audio_fd as well, because there is not serial signaling of incoming calls */
+ FD_ZERO(&rfds);
+ time(&now_timestamp);
+ p = skypiax_iflist;
+ while (p) {
+ if (!p->owner) {
+ /* This interface needs to be watched, as it lacks an owner */
-switch_endpoint_interface_t *skypiax_endpoint_interface;
-static switch_memory_pool_t *module_pool = NULL;
-static int running = 1;
+ if (p->skype) {
+ if (FD_ISSET(p->AsteriskHandlesAst.fdesc[0], &rfds))
+ ERRORA("Descriptor %d (AsteriskHandlesAst.fdesc[0]) appears twice ?\n",
+ SKYPIAX_P_LOG, p->AsteriskHandlesAst.fdesc[0]);
+ if (p->AsteriskHandlesAst.fdesc[0] > 0) {
+ FD_SET(p->AsteriskHandlesAst.fdesc[0], &rfds);
+ if (p->AsteriskHandlesAst.fdesc[0] > max)
+ max = p->AsteriskHandlesAst.fdesc[0];
-typedef enum {
- TFLAG_IO = (1 << 0),
- TFLAG_INBOUND = (1 << 1),
- TFLAG_OUTBOUND = (1 << 2),
- TFLAG_DTMF = (1 << 3),
- TFLAG_VOICE = (1 << 4),
- TFLAG_HANGUP = (1 << 5),
- TFLAG_LINEAR = (1 << 6),
- TFLAG_CODEC = (1 << 7),
- TFLAG_BREAK = (1 << 8)
-} TFLAGS;
+ }
+ }
-typedef enum {
- GFLAG_MY_CODEC_PREFS = (1 << 0)
-} GFLAGS;
+ }
+ /* next interface, please */
+ p = p->next;
+ }
+ /* Okay, now that we know what to do, release the interface lock */
+ MONITORUNLOCKA(&skypiax_iflock);
+ POPPA_UNLOCKA(&skypiax_iflock);
+ /* And from now on, we're okay to be killed, so release the monitor lock as well */
+ MONITORUNLOCKA(&skypiax_monlock);
+ POPPA_UNLOCKA(&skypiax_monlock);
+ /* you want me to die? */
+ pthread_testcancel();
-static struct {
- int debug;
- char *ip;
- int port;
- char *dialplan;
- char *codec_string;
- char *codec_order[SWITCH_MAX_CODECS];
- int codec_order_last;
- char *codec_rates_string;
- char *codec_rates[SWITCH_MAX_CODECS];
- int codec_rates_last;
- unsigned int flags;
- int calls;
- switch_mutex_t *mutex;
-} globals;
+ /* Wait for something to happen */
+ to.tv_sec = 0;
+ to.tv_usec = 500000; /* we select with this timeout because under cygwin we avoid the signal usage, so there is no way to end the thread if it is stuck waiting for select */
+ res = ast_select(max + 1, &rfds, NULL, NULL, &to);
-struct private_object {
- unsigned int flags;
- switch_codec_t read_codec;
- switch_codec_t write_codec;
- switch_frame_t read_frame;
- unsigned char databuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
- switch_core_session_t *session;
- switch_caller_profile_t *caller_profile;
- switch_mutex_t *mutex;
- switch_mutex_t *flag_mutex;
- //switch_thread_cond_t *cond;
-};
+ /* you want me to die? */
+ pthread_testcancel();
-typedef struct private_object private_t;
+ /* Okay, select has finished. Let's see what happened. */
+ /* If there are errors... */
+ if (res < 0) {
+ if (errno == EINTR) /* EINTR is just the select
+ being interrupted by a SIGURG, or so */
+ continue;
+ else {
+ ERRORA("select returned %d: %s\n", SKYPIAX_P_LOG, res, strerror(errno));
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return NULL;
+ }
+ }
-SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan);
-SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_codec_string, globals.codec_string);
-SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_codec_rates_string, globals.codec_rates_string);
-SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_ip, globals.ip);
+ /* must not be killed while skypiax_iflist is locked */
+ PUSHA_UNLOCKA(&skypiax_monlock);
+ MONITORLOKKA(&skypiax_monlock);
+ /* Alright, lock the interface list again, and let's look and see what has
+ happened */
+ PUSHA_UNLOCKA(&skypiax_iflock);
+ MONITORLOKKA(&skypiax_iflock);
+ p = skypiax_iflist;
+ for (; p; p = p->next) {
+ if (p->skype) {
+ if (FD_ISSET(p->AsteriskHandlesAst.fdesc[0], &rfds)) {
+ res = skypiax_skype_read(p);
+ if (res == CALLFLOW_INCOMING_CALLID || res == CALLFLOW_INCOMING_RING) {
+ //ast_log(LOG_NOTICE, "CALLFLOW_INCOMING_RING SKYPE\n");
+ DEBUGA_SKYPE("CALLFLOW_INCOMING_RING\n", SKYPIAX_P_LOG);
+ skypiax_new(p, AST_STATE_RING, p->context /* p->context */ );
+ }
+ }
+ }
-static switch_status_t channel_on_init(switch_core_session_t *session);
-static switch_status_t channel_on_hangup(switch_core_session_t *session);
-static switch_status_t channel_on_routing(switch_core_session_t *session);
-static switch_status_t channel_on_exchange_media(switch_core_session_t *session);
-static switch_status_t channel_on_soft_execute(switch_core_session_t *session);
-static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event,
- switch_caller_profile_t *outbound_profile,
- switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags);
-static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id);
-static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
-static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig);
+ }
+ MONITORUNLOCKA(&skypiax_iflock);
+ POPPA_UNLOCKA(&skypiax_iflock);
+ MONITORUNLOCKA(&skypiax_monlock);
+ POPPA_UNLOCKA(&skypiax_monlock);
+ pthread_testcancel();
+ }
+/* Never reached */
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return NULL;
+}
+/*!
+ * \brief Initialize the soundcard channels (input and output) used by one interface (a multichannel soundcard can be used by multiple interfaces)
+ * \param p the skypiax_pvt of the interface
+ *
+ * This function initialize the soundcard channels (input and output) used by one interface (a multichannel soundcard can be used by multiple interfaces). It simply pass its parameters to the right function for the sound system for which has been compiled, eg. alsa_init for ALSA, oss_init for OSS, winmm_init for Windows Multimedia, etc and return the result
+ *
+ * \return zero on success, -1 on error.
+ */
-static void tech_init(private_t *tech_pvt, switch_core_session_t *session)
+int skypiax_sound_init(struct skypiax_pvt *p)
{
- tech_pvt->read_frame.data = tech_pvt->databuf;
- tech_pvt->read_frame.buflen = sizeof(tech_pvt->databuf);
- switch_mutex_init(&tech_pvt->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
- switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
- switch_core_session_set_private(session, tech_pvt);
- tech_pvt->session = session;
+ if (option_debug > 10) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return skypiax_skypeaudio_init(p);
}
-/*
- State methods they get called when the state changes to the specific state
- returning SWITCH_STATUS_SUCCESS tells the core to execute the standard state method next
- so if you fully implement the state you can return SWITCH_STATUS_FALSE to skip it.
-*/
-static switch_status_t channel_on_init(switch_core_session_t *session)
+/*!
+ * \brief Shutdown the soundcard channels (input and output) used by one interface (a multichannel soundcard can be used by multiple interfaces)
+ * \param p the skypiax_pvt of the interface
+ *
+ * This function shutdown the soundcard channels (input and output) used by one interface (a multichannel soundcard can be used by multiple interfaces). It simply pass its parameters to the right function for the sound system for which has been compiled, eg. alsa_shutdown for ALSA, oss_shutdown for OSS, winmm_shutdown for Windows Multimedia, etc and return the result
+ *
+ * \return zero on success, -1 on error.
+ */
+
+int skypiax_sound_shutdown(struct skypiax_pvt *p)
{
- switch_channel_t *channel;
- private_t *tech_pvt = NULL;
- tech_pvt = switch_core_session_get_private(session);
- assert(tech_pvt != NULL);
+ if (option_debug > 10) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+ //return skypiax_portaudio_shutdown(p);
- channel = switch_core_session_get_channel(session);
- assert(channel != NULL);
- switch_set_flag_locked(tech_pvt, TFLAG_IO);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return -1;
+}
- /* Move channel's state machine to ROUTING. This means the call is trying
- to get from the initial start where the call because, to the point
- where a destination has been identified. If the channel is simply
- left in the initial state, nothing will happen. */
- switch_channel_set_state(channel, CS_ROUTING);
- switch_mutex_lock(globals.mutex);
- globals.calls++;
- switch_mutex_unlock(globals.mutex);
+/*! \brief Read audio frames from interface */
+struct ast_frame *skypiax_sound_read(struct skypiax_pvt *p)
+{
+ struct ast_frame *f = NULL;
- return SWITCH_STATUS_SUCCESS;
+ if (option_debug > 100) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+ f = skypiax_skypeaudio_read(p);
+ if (option_debug > 100) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return f;
+}
+
+/*! \brief Send audio frame to interface */
+int skypiax_sound_write(struct skypiax_pvt *p, struct ast_frame *f)
+{
+ int ret = -1;
+
+ if (option_debug > 100) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+ ret = skypiax_skypeaudio_write(p, f);
+ if (option_debug > 100) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return ret;
}
-static switch_status_t channel_on_routing(switch_core_session_t *session)
-{
- switch_channel_t *channel = NULL;
- private_t *tech_pvt = NULL;
+/*!
+ * \brief This thread runs during a call, and monitor the interface serial port for signaling, like hangup, caller id, etc
+ *
+ */
+void *skypiax_do_controldev_thread(void *data)
+{
+ struct skypiax_pvt *p = data;
+ int res;
+
+ if (option_debug > 10) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+ DEBUGA_SERIAL("In skypiax_do_controldev_thread: started, p=%p\n", SKYPIAX_P_LOG, p);
- channel = switch_core_session_get_channel(session);
- assert(channel != NULL);
+ if (pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL)) {
+ ERRORA("Unable to set cancel type to deferred\n", SKYPIAX_P_LOG);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return NULL;
+ }
- tech_pvt = switch_core_session_get_private(session);
- assert(tech_pvt != NULL);
+ while (1) {
+ usleep(1000);
+ pthread_testcancel();
+ if (p->skype) {
+ res = skypiax_skype_read(p);
+ if (res == CALLFLOW_INCOMING_HANGUP) {
+ if (option_debug)
+ DEBUGA_SKYPE("skype call ended\n", SKYPIAX_P_LOG);
+ if (p->owner) {
+ pthread_testcancel();
+ ast_queue_control(p->owner, AST_CONTROL_HANGUP);
+ }
+ }
+ }
+ }
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL ROUTING\n", switch_channel_get_name(channel));
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return NULL;
- return SWITCH_STATUS_SUCCESS;
}
-static switch_status_t channel_on_execute(switch_core_session_t *session)
-{
-
- switch_channel_t *channel = NULL;
- private_t *tech_pvt = NULL;
+/************************************************/
- channel = switch_core_session_get_channel(session);
- assert(channel != NULL);
+/* LUIGI RIZZO's magic */
+/*
+ * store the boost factor
+ */
+#ifdef ASTERISK_VERSION_1_6
+void skypiax_store_boost(const char *s, double *boost)
+#else
+void skypiax_store_boost(char *s, double *boost)
+#endif /* ASTERISK_VERSION_1_6 */
+{
+ struct skypiax_pvt *p = NULL;
- tech_pvt = switch_core_session_get_private(session);
- assert(tech_pvt != NULL);
+ if (option_debug > 10) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+ if (sscanf(s, "%lf", boost) != 1) {
+ ERRORA("invalid boost <%s>\n", SKYPIAX_P_LOG, s);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return;
+ }
+ if (*boost < -BOOST_MAX) {
+ WARNINGA("boost %s too small, using %d\n", SKYPIAX_P_LOG, s, -BOOST_MAX);
+ *boost = -BOOST_MAX;
+ } else if (*boost > BOOST_MAX) {
+ WARNINGA("boost %s too large, using %d\n", SKYPIAX_P_LOG, s, BOOST_MAX);
+ *boost = BOOST_MAX;
+ }
+ *boost = exp(log(10) * *boost / 20) * BOOST_SCALE;
+ if (option_debug > 1)
+ DEBUGA_SOUND("setting boost %s to %f\n", SKYPIAX_P_LOG, s, *boost);
+}
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL EXECUTE\n", switch_channel_get_name(channel));
+/*
+ * returns a pointer to the descriptor with the given name
+ */
+struct skypiax_pvt *skypiax_console_find_desc(char *dev)
+{
+ struct skypiax_pvt *p = NULL;
+ if (option_debug > 10) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+ for (p = skypiax_iflist; p && strcmp(p->name, dev) != 0; p = p->next);
+ if (p == NULL)
+ WARNINGA("could not find <%s>\n", SKYPIAX_P_LOG, dev);
- return SWITCH_STATUS_SUCCESS;
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return p;
}
-
-static switch_status_t channel_on_hangup(switch_core_session_t *session)
+int skypiax_console_playback_boost(int fd, int argc, char *argv[])
{
- switch_channel_t *channel = NULL;
- private_t *tech_pvt = NULL;
+ struct skypiax_pvt *p = skypiax_console_find_desc(skypiax_console_active);
- channel = switch_core_session_get_channel(session);
- assert(channel != NULL);
+ if (option_debug > 10) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+ if (argc > 2) {
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return RESULT_SHOWUSAGE;
+ }
+ if (!p) {
+ ast_cli(fd,
+ "No \"current\" skypiax_console for playback_boost, please enter 'help skypiax_console'\n");
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return RESULT_SUCCESS;
+ }
- tech_pvt = switch_core_session_get_private(session);
- assert(tech_pvt != NULL);
+ if (argc == 1) {
+ ast_cli(fd, "playback_boost on the active skypiax_console, that is [%s], is: %5.1f\n",
+ skypiax_console_active,
+ 20 * log10(((double) p->playback_boost / (double) BOOST_SCALE)));
+ } else if (argc == 2) {
+ skypiax_store_boost(argv[1], &p->playback_boost);
- switch_clear_flag_locked(tech_pvt, TFLAG_IO);
- switch_clear_flag_locked(tech_pvt, TFLAG_VOICE);
- //switch_thread_cond_signal(tech_pvt->cond);
+ ast_cli(fd,
+ "playback_boost on the active skypiax_console, that is [%s], is now: %5.1f\n",
+ skypiax_console_active,
+ 20 * log10(((double) p->playback_boost / (double) BOOST_SCALE)));
+ }
- if (tech_pvt->read_codec.implementation) {
- switch_core_codec_destroy(&tech_pvt->read_codec);
- }
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return RESULT_SUCCESS;
+}
+int skypiax_console_capture_boost(int fd, int argc, char *argv[])
+{
+ struct skypiax_pvt *p = skypiax_console_find_desc(skypiax_console_active);
- if (tech_pvt->write_codec.implementation) {
- switch_core_codec_destroy(&tech_pvt->write_codec);
- }
+ if (option_debug > 10) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+ if (argc > 2) {
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return RESULT_SHOWUSAGE;
+ }
+ if (!p) {
+ ast_cli(fd,
+ "No \"current\" skypiax_console for capture_boost, please enter 'help skypiax_console'\n");
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return RESULT_SUCCESS;
+ }
+ if (argc == 1) {
+ ast_cli(fd, "capture_boost on the active skypiax_console, that is [%s], is: %5.1f\n",
+ skypiax_console_active,
+ 20 * log10(((double) p->capture_boost / (double) BOOST_SCALE)));
+ } else if (argc == 2) {
+ skypiax_store_boost(argv[1], &p->capture_boost);
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL HANGUP\n", switch_channel_get_name(channel));
- switch_mutex_lock(globals.mutex);
- globals.calls--;
- if (globals.calls < 0) {
- globals.calls = 0;
- }
- switch_mutex_unlock(globals.mutex);
+ ast_cli(fd,
+ "capture_boost on the active skypiax_console, that is [%s], is now: %5.1f\n",
+ skypiax_console_active,
+ 20 * log10(((double) p->capture_boost / (double) BOOST_SCALE)));
+ }
- return SWITCH_STATUS_SUCCESS;
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return RESULT_SUCCESS;
}
-static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig)
+int skypiax_console_hangup(int fd, int argc, char *argv[])
{
- switch_channel_t *channel = NULL;
- private_t *tech_pvt = NULL;
+ struct skypiax_pvt *p = skypiax_console_find_desc(skypiax_console_active);
- channel = switch_core_session_get_channel(session);
- assert(channel != NULL);
+ if (option_debug > 10) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+ if (argc != 1) {
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return RESULT_SHOWUSAGE;
+ }
+ if (!p) {
+ ast_cli(fd,
+ "No \"current\" skypiax_console for hanging up, please enter 'help skypiax_console'\n");
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return RESULT_SUCCESS;
+ }
+ if (!p->owner) {
+ ast_cli(fd, "No call to hangup on the active skypiax_console, that is [%s]\n",
+ skypiax_console_active);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return RESULT_FAILURE;
+ }
+ if (p->owner)
+ ast_queue_hangup(p->owner);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return RESULT_SUCCESS;
+}
- tech_pvt = switch_core_session_get_private(session);
- assert(tech_pvt != NULL);
+int skypiax_console_dial(int fd, int argc, char *argv[])
+{
+ char *s = NULL;
+ struct skypiax_pvt *p = skypiax_console_find_desc(skypiax_console_active);
- switch (sig) {
- case SWITCH_SIG_KILL:
- switch_clear_flag_locked(tech_pvt, TFLAG_IO);
- switch_clear_flag_locked(tech_pvt, TFLAG_VOICE);
- switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
- //switch_thread_cond_signal(tech_pvt->cond);
- break;
- case SWITCH_SIG_BREAK:
- switch_set_flag_locked(tech_pvt, TFLAG_BREAK);
- break;
- default:
- break;
- }
+ if (option_debug > 10) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+ if (argc != 2) {
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return RESULT_SHOWUSAGE;
+ }
+ if (!p) {
+ ast_cli(fd,
+ "No \"current\" skypiax_console for dialing, please enter 'help skypiax_console'\n");
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return RESULT_SUCCESS;
+ }
- return SWITCH_STATUS_SUCCESS;
-}
+ if (p->owner) { /* already in a call */
+ int i;
+ struct ast_frame f = { AST_FRAME_DTMF, 0 };
-static switch_status_t channel_on_exchange_media(switch_core_session_t *session)
-{
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CHANNEL LOOPBACK\n");
- return SWITCH_STATUS_SUCCESS;
+ s = argv[1];
+ /* send the string one char at a time */
+ for (i = 0; i < strlen(s); i++) {
+ f.subclass = s[i];
+ ast_queue_frame(p->owner, &f);
+ }
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return RESULT_SUCCESS;
+ } else
+ ast_cli(fd,
+ "No call in which to dial on the \"current\" skypiax_console, that is [%s]\n",
+ skypiax_console_active);
+ if (s)
+ free(s);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return RESULT_SUCCESS;
}
-
-static switch_status_t channel_on_soft_execute(switch_core_session_t *session)
+int skypiax_console_set_active(int fd, int argc, char *argv[])
{
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CHANNEL TRANSMIT\n");
- return SWITCH_STATUS_SUCCESS;
+ if (argc == 1)
+ ast_cli(fd,
+ "\"current\" skypiax_console is [%s]\n Enter 'skypiax_console show' to see the available interfaces.\n Enter 'skypiax_console interfacename' to change the \"current\" skypiax_console.\n",
+ skypiax_console_active);
+ else if (argc != 2) {
+ return RESULT_SHOWUSAGE;
+ } else {
+ struct skypiax_pvt *p;
+ if (strcmp(argv[1], "show") == 0) {
+ ast_cli(fd, "Available interfaces:\n");
+ for (p = skypiax_iflist; p; p = p->next)
+ ast_cli(fd, " [%s]\n", p->name);
+ return RESULT_SUCCESS;
+ }
+ p = skypiax_console_find_desc(argv[1]);
+ if (p == NULL)
+ ast_cli(fd, "Interface [%s] do not exists!\n", argv[1]);
+ else {
+ skypiax_console_active = p->name;
+ ast_cli(fd, "\"current\" skypiax_console is now: [%s]\n", argv[1]);
+ }
+ }
+ return RESULT_SUCCESS;
}
-static switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)
+int skypiax_console_skypiax(int fd, int argc, char *argv[])
{
- private_t *tech_pvt = switch_core_session_get_private(session);
- switch_assert(tech_pvt != NULL);
-
- return SWITCH_STATUS_SUCCESS;
+ return RESULT_SHOWUSAGE;
}
-static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
-{
- switch_channel_t *channel = NULL;
- private_t *tech_pvt = NULL;
- //switch_time_t started = switch_time_now();
- //unsigned int elapsed;
- switch_byte_t *data;
-
- channel = switch_core_session_get_channel(session);
- assert(channel != NULL);
-
- tech_pvt = switch_core_session_get_private(session);
- assert(tech_pvt != NULL);
- tech_pvt->read_frame.flags = SFF_NONE;
- *frame = NULL;
-
- while (switch_test_flag(tech_pvt, TFLAG_IO)) {
-
- if (switch_test_flag(tech_pvt, TFLAG_BREAK)) {
- switch_clear_flag(tech_pvt, TFLAG_BREAK);
- goto cng;
- }
-
- if (!switch_test_flag(tech_pvt, TFLAG_IO)) {
- return SWITCH_STATUS_FALSE;
- }
-
- if (switch_test_flag(tech_pvt, TFLAG_IO) && switch_test_flag(tech_pvt, TFLAG_VOICE)) {
- switch_clear_flag_locked(tech_pvt, TFLAG_VOICE);
- if (!tech_pvt->read_frame.datalen) {
- continue;
- }
- *frame = &tech_pvt->read_frame;
-#ifdef BIGENDIAN
- if (switch_test_flag(tech_pvt, TFLAG_LINEAR)) {
- switch_swap_linear((*frame)->data, (int) (*frame)->datalen / 2);
- }
+/************************************************/
+#ifdef ASTERISK_VERSION_1_4
+#ifndef AST_MODULE
+#define AST_MODULE "chan_skypiax"
#endif
- return SWITCH_STATUS_SUCCESS;
- }
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Skypiax, Audio-Serial Driver");
+#endif /* ASTERISK_VERSION_1_4 */
- switch_yield(1000);
- }
+/* rewriting end */
+/*******************************************************************************/
+#endif /* CHAN_SKYPIAX */
+#ifdef SKYPIAX_ADDITIONAL
+//indent -gnu -ts4 -br -brs -cdw -lp -ce -nbfda -npcs -nprs -npsl -nbbo -saf -sai -saw -cs -bbo -nhnl -nut -sob -l90
+#include "skypiax.h"
+extern int skypiax_debug;
+extern char *skypiax_console_active;
+extern char skypiax_type[];
+extern struct skypiax_pvt *skypiax_iflist;
+//extern int directoriax_entry_extension;
- return SWITCH_STATUS_FALSE;
+/* GLOBALS */
+int skypiax_dir_entry_extension=1;
- cng:
- data = (switch_byte_t *) tech_pvt->read_frame.data;
- data[0] = 65;
- data[1] = 0;
- tech_pvt->read_frame.datalen = 2;
- tech_pvt->read_frame.flags = SFF_CNG;
- *frame = &tech_pvt->read_frame;
- return SWITCH_STATUS_SUCCESS;
+#ifdef __CYGWIN__
+struct AsteriskHandles *win32_AsteriskHandlesSkype;
+HWND win32_hInit_MainWindowHandle;
+HINSTANCE win32_hInit_ProcessHandle;
+char win32_acInit_WindowClassName[128];
+HANDLE win32_hGlobal_ThreadShutdownEvent;
+UINT win32_uiGlobal_MsgID_SkypeControlAPIAttach;
+UINT win32_uiGlobal_MsgID_SkypeControlAPIDiscover;
+HWND win32_hGlobal_SkypeAPIWindowHandle = NULL;
+DWORD win32_ulGlobal_PromptConsoleMode = 0;
+HANDLE volatile win32_hGlobal_PromptConsoleHandle = NULL;
-}
+enum {
+ SKYPECONTROLAPI_ATTACH_SUCCESS = 0, /* Client is successfully
+ attached and API window handle can be found
+ in wParam parameter */
+ SKYPECONTROLAPI_ATTACH_PENDING_AUTHORIZATION = 1, /* Skype has acknowledged
+ connection request and is waiting
+ for confirmation from the user. */
+ /* The client is not yet attached
+ * and should wait for SKYPECONTROLAPI_ATTACH_SUCCESS message */
+ SKYPECONTROLAPI_ATTACH_REFUSED = 2, /* User has explicitly
+ denied access to client */
+ SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE = 3, /* API is not available
+ at the moment.
+ For example, this happens when no user
+ is currently logged in. */
+ /* Client should wait for
+ * SKYPECONTROLAPI_ATTACH_API_AVAILABLE
+ * broadcast before making any further */
+ /* connection attempts. */
+ SKYPECONTROLAPI_ATTACH_API_AVAILABLE = 0x8001
+};
-static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
+LRESULT APIENTRY skypiax_skype_present(HWND hWindow, UINT uiMessage, WPARAM uiParam,
+ LPARAM ulParam)
{
- switch_channel_t *channel = NULL;
- private_t *tech_pvt = NULL;
- //switch_frame_t *pframe;
-
- channel = switch_core_session_get_channel(session);
- assert(channel != NULL);
-
- tech_pvt = switch_core_session_get_private(session);
- assert(tech_pvt != NULL);
-
- if (!switch_test_flag(tech_pvt, TFLAG_IO)) {
- return SWITCH_STATUS_FALSE;
- }
-#ifdef BIGENDIAN
- if (switch_test_flag(tech_pvt, TFLAG_LINEAR)) {
- switch_swap_linear(frame->data, (int) frame->datalen / 2);
- }
-#endif
-
+ LRESULT lReturnCode;
+ int fIssueDefProc;
+ struct skypiax_pvt *p = NULL;
- return SWITCH_STATUS_SUCCESS;
+ lReturnCode = 0;
+ fIssueDefProc = 0;
+ switch (uiMessage) {
+ case WM_DESTROY:
+ win32_hInit_MainWindowHandle = NULL;
+ PostQuitMessage(0);
+ break;
+ case WM_COPYDATA:
+ if (win32_hGlobal_SkypeAPIWindowHandle == (HWND) uiParam) {
+ PCOPYDATASTRUCT poCopyData = (PCOPYDATASTRUCT) ulParam;
+ write(win32_AsteriskHandlesSkype->fdesc[1], (const char *) poCopyData->lpData,
+ strlen((const char *) poCopyData->lpData));
+ write(win32_AsteriskHandlesSkype->fdesc[1], "\0", 1);
+ lReturnCode = 1;
+ }
+ break;
+ default:
+ if (uiMessage == win32_uiGlobal_MsgID_SkypeControlAPIAttach) {
+ switch (ulParam) {
+ case SKYPECONTROLAPI_ATTACH_SUCCESS:
+ NOTICA("\n\n\tConnected to Skype API!\n", SKYPIAX_P_LOG);
+ win32_hGlobal_SkypeAPIWindowHandle = (HWND) uiParam;
+ usleep(5000);
+ win32_AsteriskHandlesSkype->win32_hGlobal_SkypeAPIWindowHandle =
+ win32_hGlobal_SkypeAPIWindowHandle;
+ break;
+ case SKYPECONTROLAPI_ATTACH_PENDING_AUTHORIZATION:
+ WARNINGA
+ ("\n\n\tIf I do not immediately connect to Skype API,\n\tplease give the Skype client authorization to be connected \n\tby Asterisk and to not ask you again.\n\n",
+ SKYPIAX_P_LOG);
+ break;
+ case SKYPECONTROLAPI_ATTACH_REFUSED:
+ ERRORA("Skype client refused to be connected by Skypiax!\n", SKYPIAX_P_LOG);
+ break;
+ case SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE:
+ ERRORA("Skype API not available\n", SKYPIAX_P_LOG);
+ break;
+ case SKYPECONTROLAPI_ATTACH_API_AVAILABLE:
+ DEBUGA_SKYPE("Skype API available\n", SKYPIAX_P_LOG);
+ break;
+ default:
+ WARNINGA("GOT AN UNKNOWN SKYPE WINDOWS MSG\n", SKYPIAX_P_LOG);
+ }
+ lReturnCode = 1;
+ break;
+ }
+ fIssueDefProc = 1;
+ break;
+ }
+ if (fIssueDefProc)
+ lReturnCode = DefWindowProc(hWindow, uiMessage, uiParam, ulParam);
+ return (lReturnCode);
}
-static switch_status_t channel_answer_channel(switch_core_session_t *session)
+int win32_Initialize_CreateWindowClass(void)
{
- private_t *tech_pvt;
- switch_channel_t *channel = NULL;
+ unsigned char *paucUUIDString;
+ RPC_STATUS lUUIDResult;
+ int fReturnStatus;
+ UUID oUUID;
- channel = switch_core_session_get_channel(session);
- assert(channel != NULL);
+ fReturnStatus = 0;
+ lUUIDResult = UuidCreate(&oUUID);
+ win32_hInit_ProcessHandle =
+ (HINSTANCE) OpenProcess(PROCESS_DUP_HANDLE, FALSE, GetCurrentProcessId());
+ if (win32_hInit_ProcessHandle != NULL
+ && (lUUIDResult == RPC_S_OK || lUUIDResult == RPC_S_UUID_LOCAL_ONLY)) {
+ if (UuidToString(&oUUID, &paucUUIDString) == RPC_S_OK) {
+ WNDCLASS oWindowClass;
- tech_pvt = switch_core_session_get_private(session);
- assert(tech_pvt != NULL);
+ strcpy(win32_acInit_WindowClassName, "Skype-API-Skypiax-");
+ strcat(win32_acInit_WindowClassName, (char *) paucUUIDString);
+
+ oWindowClass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
+ oWindowClass.lpfnWndProc = (WNDPROC) & skypiax_skype_present;
+ oWindowClass.cbClsExtra = 0;
+ oWindowClass.cbWndExtra = 0;
+ oWindowClass.hInstance = win32_hInit_ProcessHandle;
+ oWindowClass.hIcon = NULL;
+ oWindowClass.hCursor = NULL;
+ oWindowClass.hbrBackground = NULL;
+ oWindowClass.lpszMenuName = NULL;
+ oWindowClass.lpszClassName = win32_acInit_WindowClassName;
+ if (RegisterClass(&oWindowClass) != 0)
+ fReturnStatus = 1;
- return SWITCH_STATUS_SUCCESS;
+ RpcStringFree(&paucUUIDString);
+ }
+ }
+ if (fReturnStatus == 0)
+ CloseHandle(win32_hInit_ProcessHandle), win32_hInit_ProcessHandle = NULL;
+ return (fReturnStatus);
}
-
-static switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg)
+void win32_DeInitialize_DestroyWindowClass(void)
{
- switch_channel_t *channel;
- private_t *tech_pvt;
-
- channel = switch_core_session_get_channel(session);
- assert(channel != NULL);
-
- tech_pvt = (private_t *) switch_core_session_get_private(session);
- assert(tech_pvt != NULL);
-
- switch (msg->message_id) {
- case SWITCH_MESSAGE_INDICATE_ANSWER:
- {
- channel_answer_channel(session);
- }
- break;
- default:
- break;
- }
-
- return SWITCH_STATUS_SUCCESS;
+ UnregisterClass(win32_acInit_WindowClassName, win32_hInit_ProcessHandle);
+ CloseHandle(win32_hInit_ProcessHandle), win32_hInit_ProcessHandle = NULL;
}
-/* Make sure when you have 2 sessions in the same scope that you pass the appropriate one to the routines
- that allocate memory or you will have 1 channel with memory allocated from another channel's pool!
-*/
-static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event,
- switch_caller_profile_t *outbound_profile,
- switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags)
+int win32_Initialize_CreateMainWindow(void)
{
- if ((*new_session = switch_core_session_request(skypiax_endpoint_interface, pool)) != 0) {
- private_t *tech_pvt;
- switch_channel_t *channel;
- switch_caller_profile_t *caller_profile;
+ win32_hInit_MainWindowHandle =
+ CreateWindowEx(WS_EX_APPWINDOW | WS_EX_WINDOWEDGE, win32_acInit_WindowClassName, "",
+ WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT,
+ 128, 128, NULL, 0, win32_hInit_ProcessHandle, 0);
+ return (win32_hInit_MainWindowHandle != NULL ? 1 : 0);
+}
- switch_core_session_add_stream(*new_session, NULL);
- if ((tech_pvt = (private_t *) switch_core_session_alloc(*new_session, sizeof(private_t))) != 0) {
- channel = switch_core_session_get_channel(*new_session);
- tech_init(tech_pvt, *new_session);
- } else {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Hey where is my memory pool?\n");
- switch_core_session_destroy(new_session);
- return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
- }
+void win32_DeInitialize_DestroyMainWindow(void)
+{
+ if (win32_hInit_MainWindowHandle != NULL)
+ DestroyWindow(win32_hInit_MainWindowHandle), win32_hInit_MainWindowHandle = NULL;
+}
- if (outbound_profile) {
- char name[128];
+DWORD win32_dwThreadId;
- snprintf(name, sizeof(name), "SKYPIAX/%s", outbound_profile->destination_number);
- switch_channel_set_name(channel, name);
+void *do_skype_thread(void *data)
+{
+ /* create window class */
+ /* create dummy/hidden window for processing messages */
+ /* run message loop thread */
+ /* do application control until exit */
+ /* exit: send QUIT message to our own window */
+ /* wait until thred terminates */
+ /* destroy main window */
+ /* destroy window class */
- caller_profile = switch_caller_profile_clone(*new_session, outbound_profile);
- switch_channel_set_caller_profile(channel, caller_profile);
- tech_pvt->caller_profile = caller_profile;
- } else {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Doh! no caller profile\n");
- switch_core_session_destroy(new_session);
- return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
- }
+ win32_AsteriskHandlesSkype = (struct AsteriskHandles *) data;
+ win32_uiGlobal_MsgID_SkypeControlAPIAttach =
+ RegisterWindowMessage("SkypeControlAPIAttach");
+ win32_uiGlobal_MsgID_SkypeControlAPIDiscover =
+ RegisterWindowMessage("SkypeControlAPIDiscover");
+ if (win32_uiGlobal_MsgID_SkypeControlAPIAttach != 0
+ && win32_uiGlobal_MsgID_SkypeControlAPIDiscover != 0) {
+ if (win32_Initialize_CreateWindowClass()) {
+ if (win32_Initialize_CreateMainWindow()) {
+ win32_hGlobal_ThreadShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (win32_hGlobal_ThreadShutdownEvent != NULL) {
+ if (SendMessage
+ (HWND_BROADCAST, win32_uiGlobal_MsgID_SkypeControlAPIDiscover,
+ (WPARAM) win32_hInit_MainWindowHandle, 0) != 0) {
+ win32_AsteriskHandlesSkype->win32_hInit_MainWindowHandle =
+ win32_hInit_MainWindowHandle;
+ while (1) {
+ MSG oMessage;
- switch_channel_set_flag(channel, CF_OUTBOUND);
- switch_set_flag_locked(tech_pvt, TFLAG_OUTBOUND);
- switch_channel_set_state(channel, CS_INIT);
- return SWITCH_CAUSE_SUCCESS;
- }
+ while (GetMessage(&oMessage, 0, 0, 0) != FALSE) {
+ TranslateMessage(&oMessage);
+ DispatchMessage(&oMessage);
+ }
+ }
+ }
+ CloseHandle(win32_hGlobal_ThreadShutdownEvent);
+ }
+ win32_DeInitialize_DestroyMainWindow();
+ }
+ win32_DeInitialize_DestroyWindowClass();
+ }
+ }
+ return NULL;
+}
- return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+#endif /* __CYGWIN__ */
-}
+#ifdef WANT_SKYPE_X11
+#define SKYPE_X11_BUF_SIZE 512
+Window skype_win = (Window) - 1;
+static XErrorHandler old_handler = 0;
+static int xerror = 0;
-static switch_status_t channel_receive_event(switch_core_session_t *session, switch_event_t *event)
+int X11_errors_handler(Display * dpy, XErrorEvent * err)
{
- struct private_object *tech_pvt = switch_core_session_get_private(session);
- char *body = switch_event_get_body(event);
- switch_assert(tech_pvt != NULL);
-
- if (!body) {
- body = "";
- }
+ (void) dpy;
+ struct skypiax_pvt *p = NULL;
- return SWITCH_STATUS_SUCCESS;
+ xerror = err->error_code;
+ DEBUGA_SKYPE("Received error code %d from X Server\n", SKYPIAX_P_LOG, xerror);
+ return 0; /* ignore the error */
}
+static void X11_errors_trap(void)
+{
+ xerror = 0;
+ old_handler = XSetErrorHandler(X11_errors_handler);
+}
+static int X11_errors_untrap(void)
+{
+ XSetErrorHandler(old_handler);
+ return (xerror != BadValue) && (xerror != BadWindow);
+}
-switch_state_handler_table_t skypiax_state_handlers = {
- /*.on_init */ channel_on_init,
- /*.on_routing */ channel_on_routing,
- /*.on_execute */ channel_on_execute,
- /*.on_hangup */ channel_on_hangup,
- /*.on_exchange_media */ channel_on_exchange_media,
- /*.on_soft_execute */ channel_on_soft_execute
-};
-
-switch_io_routines_t skypiax_io_routines = {
- /*.outgoing_channel */ channel_outgoing_channel,
- /*.read_frame */ channel_read_frame,
- /*.write_frame */ channel_write_frame,
- /*.kill_channel */ channel_kill_channel,
- /*.send_dtmf */ channel_send_dtmf,
- /*.receive_message */ channel_receive_message,
- /*.receive_event */ channel_receive_event
-};
-
-static switch_status_t load_config(void)
+int skypiax_skype_send_message(struct AsteriskHandles *AsteriskHandlesAst,
+ const char *message_P)
{
- char *cf = "skypiax.conf";
- switch_xml_t cfg, xml, settings, param;
- memset(&globals, 0, sizeof(globals));
- switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, module_pool);
- if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", cf);
- return SWITCH_STATUS_TERM;
- }
+ Window w_P;
+ Display *disp;
+ Window handle_P;
+ struct skypiax_pvt *p = NULL;
- if ((settings = switch_xml_child(cfg, "settings"))) {
- for (param = switch_xml_child(settings, "param"); param; param = param->next) {
- char *var = (char *) switch_xml_attr_soft(param, "name");
- char *val = (char *) switch_xml_attr_soft(param, "value");
+ w_P = AsteriskHandlesAst->skype_win;
+ disp = AsteriskHandlesAst->disp;
+ handle_P = AsteriskHandlesAst->win;
- if (!strcmp(var, "debug")) {
- globals.debug = atoi(val);
- } else if (!strcmp(var, "port")) {
- globals.port = atoi(val);
- } else if (!strcmp(var, "ip")) {
- set_global_ip(val);
- } else if (!strcmp(var, "codec-master")) {
- if (!strcasecmp(val, "us")) {
- switch_set_flag(&globals, GFLAG_MY_CODEC_PREFS);
- }
- } else if (!strcmp(var, "dialplan")) {
- set_global_dialplan(val);
- } else if (!strcmp(var, "codec-prefs")) {
- set_global_codec_string(val);
- globals.codec_order_last = switch_separate_string(globals.codec_string, ',', globals.codec_order, SWITCH_MAX_CODECS);
- } else if (!strcmp(var, "codec-rates")) {
- set_global_codec_rates_string(val);
- globals.codec_rates_last = switch_separate_string(globals.codec_rates_string, ',', globals.codec_rates, SWITCH_MAX_CODECS);
- }
- }
- }
+ Atom atom1 = XInternAtom(disp, "SKYPECONTROLAPI_MESSAGE_BEGIN", False);
+ Atom atom2 = XInternAtom(disp, "SKYPECONTROLAPI_MESSAGE", False);
+ unsigned int pos = 0;
+ unsigned int len = strlen(message_P);
+ XEvent e;
+ int ok;
- if (!globals.dialplan) {
- set_global_dialplan("default");
- }
+ memset(&e, 0, sizeof(e));
+ e.xclient.type = ClientMessage;
+ e.xclient.message_type = atom1; /* leading message */
+ e.xclient.display = disp;
+ e.xclient.window = handle_P;
+ e.xclient.format = 8;
- if (!globals.port) {
- globals.port = 4569;
- }
+ X11_errors_trap();
+ //XLockDisplay(disp);
+ do {
+ unsigned int i;
+ for (i = 0; i < 20 && i + pos <= len; ++i)
+ e.xclient.data.b[i] = message_P[i + pos];
+ XSendEvent(disp, w_P, False, 0, &e);
- switch_xml_free(xml);
+ e.xclient.message_type = atom2; /* following messages */
+ pos += i;
+ } while (pos <= len);
- return SWITCH_STATUS_SUCCESS;
-}
+ XSync(disp, False);
+ //XUnlockDisplay(disp);
+ ok = X11_errors_untrap();
-SWITCH_MODULE_LOAD_FUNCTION(mod_skypiax_load)
-{
+ if (!ok)
+ DEBUGA_SKYPE("Sending message failed with status %d\n", SKYPIAX_P_LOG, xerror);
- module_pool = pool;
+ return ok;
+}
- load_config();
+int skypiax_skype_present(Display * disp)
+{
+ Atom skype_inst = XInternAtom(disp, "_SKYPE_INSTANCE", True);
- *module_interface = switch_loadable_module_create_module_interface(pool, modname);
- skypiax_endpoint_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE);
- skypiax_endpoint_interface->interface_name = "skypiax";
- skypiax_endpoint_interface->io_routines = &skypiax_io_routines;
- skypiax_endpoint_interface->state_handler = &skypiax_state_handlers;
+ Atom type_ret;
+ int format_ret;
+ unsigned long nitems_ret;
+ unsigned long bytes_after_ret;
+ unsigned char *prop;
+ int status;
+ struct skypiax_pvt *p = NULL;
+ X11_errors_trap();
+ //XLockDisplay(disp);
+ status =
+ XGetWindowProperty(disp, DefaultRootWindow(disp), skype_inst, 0, 1, False, XA_WINDOW,
+ &type_ret, &format_ret, &nitems_ret, &bytes_after_ret, &prop);
+ //XUnlockDisplay(disp);
+ X11_errors_untrap();
+ /* sanity check */
+ if (status != Success || format_ret != 32 || nitems_ret != 1) {
+ skype_win = (Window) - 1;
+ DEBUGA_SKYPE("Skype instance not found\n", SKYPIAX_P_LOG);
+ return 0;
+ }
- /* indicate that the module should continue to be loaded */
- return SWITCH_STATUS_SUCCESS;
+ skype_win = *(const unsigned long *) prop & 0xffffffff;
+ //DEBUGA_SKYPE("Skype instance found with id #%x\n", SKYPIAX_P_LOG,
+ DEBUGA_SKYPE("Skype instance found with id #%d\n", SKYPIAX_P_LOG,
+ (unsigned int) skype_win);
+ return 1;
}
-/*
-SWITCH_MODULE_RUNTIME_FUNCTION(mod_skypiax_runtime)
+void skypiax_skype_clean_disp(void *data)
{
- return SWITCH_STATUS_TERM;
-}
-*/
-SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_skypiax_shutdown)
-{
- int x = 0;
+ int *dispptr;
+ int disp;
+ struct skypiax_pvt *p = NULL;
- running = -1;
+ dispptr = data;
+ disp = *dispptr;
- while (running) {
- if (x++ > 100) {
- break;
- }
- switch_yield(20000);
- }
- return SWITCH_STATUS_SUCCESS;
+ if (disp) {
+ DEBUGA_SKYPE("to be destroyed disp %d\n", SKYPIAX_P_LOG, disp);
+ close(disp);
+ DEBUGA_SKYPE("destroyed disp\n", SKYPIAX_P_LOG);
+ } else {
+ DEBUGA_SKYPE("NOT destroyed disp\n", SKYPIAX_P_LOG);
+ }
+ DEBUGA_SKYPE("OUT destroyed disp\n", SKYPIAX_P_LOG);
+ usleep(1000);
}
+void *do_skype_thread(void *data)
+{
-/* For Emacs:
- * Local Variables:
- * mode:c
- * indent-tabs-mode:t
- * tab-width:4
- * c-basic-offset:4
- * End:
- * For VIM:
- * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
- */
+ struct skypiax_pvt *p;
+ struct AsteriskHandles *AsteriskHandlesAst;
+ char buf[SKYPE_X11_BUF_SIZE];
+ Display *disp = NULL;
+ Window root = -1;
+ Window win = -1;
-#ifdef SKYPIAX_H
+ p = data;
-//indent -gnu -ts4 -br -brs -cdw -lp -ce -nbfda -npcs -nprs -npsl -nbbo -saf -sai -saw -cs -bbo -nhnl -nut -sob -l90
-#ifndef _SKYPIAX_H_
-#define _SKYPIAX_H_
+ if (option_debug > 10) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+ if (pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL)) {
+ ERRORA("Unable to set cancel type to deferred\n", SKYPIAX_P_LOG);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return NULL;
+ }
-#ifndef SKYPIAX_SVN_VERSION
-#define SKYPIAX_SVN_VERSION "????NO_REVISION???"
-#endif
+ AsteriskHandlesAst = &p->AsteriskHandlesAst;
-#include <asterisk/version.h> /* needed here for conditional compilation on version.h */
- /* the following #defs are for LINUX */
-#ifndef __CYGWIN__
-#ifndef ASTERISK_VERSION_1_6
-#ifndef ASTERISK_VERSION_1_4
-#ifndef ASTERISK_VERSION_1_2
-#define ASTERISK_VERSION_1_4
-#if(ASTERISK_VERSION_NUM == 999999)
-#undef ASTERISK_VERSION_1_4
-#elif(ASTERISK_VERSION_NUM < 10400)
-#undef ASTERISK_VERSION_1_4
-#endif /* ASTERISK_VERSION_NUM == 999999 || ASTERISK_VERSION_NUM < 10400 */
-#endif /* ASTERISK_VERSION_1_2 */
-#endif /* ASTERISK_VERSION_1_4 */
-#endif /* ASTERISK_VERSION_1_6 */
-#ifdef ASTERISK_VERSION_1_2
-#undef ASTERISK_VERSION_1_4
-#endif /* ASTERISK_VERSION_1_2 */
-#ifdef ASTERISK_VERSION_1_6
-#define ASTERISK_VERSION_1_4
-#endif /* ASTERISK_VERSION_1_6 */
-#define SKYPIAX_SKYPE
-#define WANT_SKYPE_X11
-#endif /* NOT __CYGWIN__ */
- /* the following #defs are for WINDOWS */
-#ifdef __CYGWIN__
-#undef ASTERISK_VERSION_1_4
-#undef ASTERISK_VERSION_1_6
-#define SKYPIAX_SKYPE
-#undef WANT_SKYPE_X11
-#endif /* __CYGWIN__ */
+ disp = XOpenDisplay(getenv("DISPLAY"));
+ if (!disp) {
+ ERRORA("Cannot open X Display, exiting skype thread\n", SKYPIAX_P_LOG);
+ p->skype = 0;
+ p->skype_thread = AST_PTHREADT_NULL;
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return NULL;
+ }
-/* INCLUDES */
-#ifdef ASTERISK_VERSION_1_6
-#include <asterisk.h> /* some asterisk-devel package do not contains asterisk.h, but seems that is needed for the 1.6 series, at least from trunk */
-#endif /* ASTERISK_VERSION_1_6 */
-#include <unistd.h>
-#include <termios.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <math.h>
-#include <sys/ioctl.h>
-#include <sys/time.h>
-#include <string.h>
-#include <sys/types.h>
-#include <signal.h>
-#include <ctype.h>
-#ifndef ASTERISK_VERSION_1_4
-#include <stdlib.h>
-#include <stdio.h>
-#endif /* ASTERISK_VERSION_1_4 */
-#include <asterisk/frame.h>
-#include <asterisk/channel.h>
-#include <asterisk/module.h>
-#include <asterisk/options.h>
-#include <asterisk/pbx.h>
-#include <asterisk/config.h>
-#include <asterisk/cli.h>
-#include <asterisk/causes.h>
-#include <asterisk/endian.h>
-#include <asterisk/lock.h>
-#include <asterisk/devicestate.h>
-#include <asterisk/file.h>
-#include <asterisk/say.h>
-#ifdef ASTERISK_VERSION_1_6
-#include <asterisk/astobj2.h>
-#include <asterisk/paths.h>
-#endif /* ASTERISK_VERSION_1_6 */
-#ifdef ASTERISK_VERSION_1_4
-#include <asterisk/stringfields.h>
-#include <asterisk/abstract_jb.h>
-#include <asterisk/logger.h>
-#include <asterisk/utils.h>
-#endif /* ASTERISK_VERSION_1_4 */
-#ifdef ASTERISK_VERSION_1_2
-#include <asterisk/utils.h>
-#include <asterisk/logger.h>
-#endif /* ASTERISK_VERSION_1_2 */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-//#include "skypiax_spandsp.h"
-#ifdef __CYGWIN__
-#include <windows.h>
-#endif /* __CYGWIN__ */
-#ifdef WANT_SKYPE_X11
-#include <X11/Xlib.h>
-#include <X11/Xlibint.h>
-#include <X11/Xatom.h>
-#endif /* WANT_SKYPE_X11 */
-#ifndef AST_DIGIT_ANYDIG
-#define AST_DIGIT_ANYDIG "0123456789*#"
-#else
-#warning Please review Skypiax AST_DIGIT_ANYDIG
-#endif
-#ifndef _ASTERISK_H
-#define AST_CONFIG_MAX_PATH 255 /* defined in asterisk.h, but some asterisk-devel package do not contains asterisk.h */
-extern char ast_config_AST_CONFIG_DIR[AST_CONFIG_MAX_PATH];
-int ast_register_atexit(void (*func) (void)); /* in asterisk.h, but some asterisk-devel package do not contains asterisk.h */
-void ast_unregister_atexit(void (*func) (void)); /* in asterisk.h, but some asterisk-devel package do not contains asterisk.h */
-#endif
+ int xfd;
+ xfd = XConnectionNumber(disp);
+ fcntl(xfd, F_SETFD, FD_CLOEXEC);
+ pthread_cleanup_push(skypiax_skype_clean_disp, &xfd);
+ DEBUGA_SKYPE("PUSH disp %d\n", SKYPIAX_P_LOG, xfd);
-/* DEFINITIONS */
-/* LUIGI RIZZO's magic */
-/* boost support. BOOST_SCALE * 10 ^(BOOST_MAX/20) must
- * be representable in 16 bits to avoid overflows.
- */
-#define BOOST_SCALE (1<<9)
-#define BOOST_MAX 40 /* slightly less than 7 bits */
-/* call flow from the device */
-#define CALLFLOW_CALL_IDLE AST_STATE_DOWN
-#define CALLFLOW_INCOMING_RING AST_STATE_RING
-#define CALLFLOW_CALL_DIALING AST_STATE_DIALING
-#define CALLFLOW_CALL_LINEBUSY AST_STATE_BUSY
-#define CALLFLOW_CALL_ACTIVE 300
-#define CALLFLOW_INCOMING_HANGUP 100
-#define CALLFLOW_CALL_RELEASED 101
-#define CALLFLOW_CALL_NOCARRIER 102
-#define CALLFLOW_CALL_INFLUX 103
-#define CALLFLOW_CALL_INCOMING 104
-#define CALLFLOW_CALL_FAILED 105
-#define CALLFLOW_CALL_NOSERVICE 106
-#define CALLFLOW_CALL_OUTGOINGRESTRICTED 107
-#define CALLFLOW_CALL_SECURITYFAIL 108
-#define CALLFLOW_CALL_NOANSWER 109
-#define CALLFLOW_STATUS_FINISHED 110
-#define CALLFLOW_STATUS_CANCELLED 111
-#define CALLFLOW_STATUS_FAILED 112
-#define CALLFLOW_STATUS_REFUSED 113
-#define CALLFLOW_STATUS_RINGING 114
-#define CALLFLOW_STATUS_INPROGRESS 115
-#define CALLFLOW_STATUS_UNPLACED 116
-#define CALLFLOW_STATUS_ROUTING 117
-#define CALLFLOW_STATUS_EARLYMEDIA 118
-#define AST_STATE_HANGUP_REQUESTED 200
- //FIXME CALLFLOW_INCOMING_CALLID to be removed
-#define CALLFLOW_INCOMING_CALLID 1019
-/* debugging bitmask */
-#define DEBUG_SOUND 1
-#define DEBUG_SERIAL 2
-#define DEBUG_SKYPE 4
-#define DEBUG_AT 8
-#define DEBUG_FBUS2 16
-#define DEBUG_CALL 32
-#define DEBUG_LOCKS 64
-#define DEBUG_PBX 128
-#define DEBUG_MONITORLOCKS 256
-#define DEBUG_ALL DEBUG_SOUND|DEBUG_SERIAL|DEBUG_SKYPE|DEBUG_AT|DEBUG_FBUS2|DEBUG_CALL|DEBUG_PBX|DEBUG_LOCKS|DEBUG_MONITORLOCKS
-/* wrappers for ast_log */
-#define DEBUGA_SOUND(...) if (skypiax_debug & DEBUG_SOUND) ast_log(LOG_DEBUG, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_SOUND %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
-#define DEBUGA_SERIAL(...) if (skypiax_debug & DEBUG_SERIAL) ast_log(LOG_DEBUG, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_SERIAL %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
-#define DEBUGA_SKYPE(...) if (skypiax_debug & DEBUG_SKYPE) ast_log(LOG_DEBUG, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_SKYPE %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
-#define DEBUGA_AT(...) if (skypiax_debug & DEBUG_AT) ast_log(LOG_DEBUG, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_AT %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
-#define DEBUGA_FBUS2(...) if (skypiax_debug & DEBUG_FBUS2) ast_log(LOG_DEBUG, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_FBUS2 %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
-#define DEBUGA_CALL(...) if (skypiax_debug & DEBUG_CALL) ast_log(LOG_DEBUG, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_CALL %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
-#define DEBUGA_PBX(...) if (skypiax_debug & DEBUG_PBX) ast_log(LOG_DEBUG, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_PBX %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
-#define ERRORA(...) ast_log(LOG_ERROR, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][ERROR %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
-#define NOTICA(...) ast_log(LOG_NOTICE, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][NOTICE %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
-#define WARNINGA(...) ast_log(LOG_WARNING, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][WARNING %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
-/* macros for logging */
-#define SKYPIAX_P_LOG p ? p->owner : NULL, (unsigned long)pthread_self(), __LINE__, p ? p->name ? p->name : "none" : "none", p ? p->owner ? p->owner->_state : -1 : -1, p ? p->interface_state : -1, p ? p->skype_callflow : -1
-#define SKYPIAX_TMP_LOG tmp ? tmp->owner : NULL, (unsigned long)pthread_self(), __LINE__, tmp ? tmp->name ? tmp->name : "none" : "none", tmp ? tmp->owner ? tmp->owner->_state : -1 : -1, tmp ? tmp->interface_state : -1, tmp ? tmp->skype_callflow : -1
-/* logging wrappers for ast_mutex_lock and ast_mutex_unlock */
-#define LOKKA(x) if (skypiax_debug & DEBUG_LOCKS) ast_log(LOG_DEBUG, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_LOCKS %-5d][%-10s][%2d,%2d,%2d] going to lock %p (%s)\n", SKYPIAX_P_LOG, x, x == &skypiax_monlock ? "MONLOCK" : x == &skypiax_iflock ? "IFLOCK" : x == &skypiax_usecnt_lock ? "USECNT_LOCK" : "?????"); if (ast_mutex_lock(x)) ast_log(LOG_ERROR, "ast_mutex_lock failed, BAD\n"); if (skypiax_debug & DEBUG_LOCKS) ast_log(LOG_DEBUG, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_LOCKS %-5d][%-10s][%2d,%2d,%2d] locked %p (%s)\n", SKYPIAX_P_LOG, x, x == &skypiax_monlock ? "MONLOCK" : x == &skypiax_iflock ? "IFLOCK" : x == &skypiax_usecnt_lock ? "USECNT_LOCK" : "?????");
-#define UNLOCKA(x) if (skypiax_debug & DEBUG_LOCKS) ast_log(LOG_DEBUG, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_LOCKS %-5d][%-10s][%2d,%2d,%2d] going to unlock %p (%s)\n", SKYPIAX_P_LOG, x, x == &skypiax_monlock ? "MONLOCK" : x == &skypiax_iflock ? "IFLOCK" : x == &skypiax_usecnt_lock ? "USECNT_LOCK" : "?????"); if (ast_mutex_unlock(x)) ast_log(LOG_ERROR, "ast_mutex_lock failed, BAD\n"); if (skypiax_debug & DEBUG_LOCKS) ast_log(LOG_DEBUG, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_LOCKS %-5d][%-10s][%2d,%2d,%2d] unlocked %p (%s)\n", SKYPIAX_P_LOG, x, x == &skypiax_monlock ? "MONLOCK" : x == &skypiax_iflock ? "IFLOCK" : x == &skypiax_usecnt_lock ? "USECNT_LOCK" : "?????");
-#define PUSHA_UNLOCKA(x) pthread_cleanup_push(skypiax_unlocka_log, (void *) x);
-#define POPPA_UNLOCKA(x) pthread_cleanup_pop(0);
-#define MONITORLOKKA(x) if (skypiax_debug & DEBUG_MONITORLOCKS) ast_log(LOG_DEBUG, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_MONITORLOCKS %-5d][%-10s][%2d,%2d,%2d] going to lock %p (%s)\n", SKYPIAX_P_LOG, x, x == &skypiax_monlock ? "MONLOCK" : x == &skypiax_iflock ? "IFLOCK" : x == &skypiax_usecnt_lock ? "USECNT_LOCK" : "?????"); if (ast_mutex_lock(x)) ast_log(LOG_ERROR, "ast_mutex_lock failed, BAD\n"); if (skypiax_debug & DEBUG_MONITORLOCKS) ast_log(LOG_DEBUG, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_MONITORLOCKS %-5d][%-10s][%2d,%2d,%2d] locked %p (%s)\n", SKYPIAX_P_LOG, x, x == &skypiax_monlock ? "MONLOCK" : x == &skypiax_iflock ? "IFLOCK" : x == &skypiax_usecnt_lock ? "USECNT_LOCK" : "?????");
-#define MONITORUNLOCKA(x) if (skypiax_debug & DEBUG_MONITORLOCKS) ast_log(LOG_DEBUG, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_MONITORLOCKS %-5d][%-10s][%2d,%2d,%2d] going to unlock %p (%s)\n", SKYPIAX_P_LOG, x, x == &skypiax_monlock ? "MONLOCK" : x == &skypiax_iflock ? "IFLOCK" : x == &skypiax_usecnt_lock ? "USECNT_LOCK" : "?????"); if (ast_mutex_unlock(x)) ast_log(LOG_ERROR, "ast_mutex_lock failed, BAD\n"); if (skypiax_debug & DEBUG_MONITORLOCKS) ast_log(LOG_DEBUG, "rev "SKYPIAX_SVN_VERSION "[%p|%-7lx][DEBUG_MONITORLOCKS %-5d][%-10s][%2d,%2d,%2d] unlocked %p (%s)\n", SKYPIAX_P_LOG, x, x == &skypiax_monlock ? "MONLOCK" : x == &skypiax_iflock ? "IFLOCK" : x == &skypiax_usecnt_lock ? "USECNT_LOCK" : "?????");
-/* macros used for config file parsing (luigi rizzo)*/
-#define M_BOOL(tag, dst) M_F(tag, (dst) = ast_true(__val) )
-#define M_END(x) x;
-#define M_F(tag, f) if (!strcasecmp((__s), tag)) { f; } else
-#ifdef ASTERISK_VERSION_1_6
-#define M_START(var, val) const char *__s = var; const char *__val = val;
-#else
-#define M_START(var, val) char *__s = var; char *__val = val;
-#endif /* ASTERISK_VERSION_1_6 */
-#define M_STR(tag, dst) M_F(tag, ast_copy_string(dst, __val, sizeof(dst)))
-#define M_UINT(tag, dst) M_F(tag, (dst) = strtoul(__val, NULL, 0) )
+ if (skypiax_skype_present(disp)) {
+ root = DefaultRootWindow(disp);
+ win =
+ XCreateSimpleWindow(disp, root, 0, 0, 1, 1, 0,
+ BlackPixel(disp, DefaultScreen(disp)), BlackPixel(disp,
+ DefaultScreen
+ (disp)));
-#define SKYPIAX_FRAME_SIZE 160
+ DEBUGA_SKYPE("skype_win=%d win=%d\n", SKYPIAX_P_LOG, (unsigned int) skype_win,
+ (unsigned int) win);
-/* SKYPIAX INTERNAL STRUCTS */
-/*!
- * \brief structure for exchanging messages with the skype client
- */
-#ifdef WANT_SKYPE_X11
-struct AsteriskHandles {
- Window skype_win;
- Display *disp;
- Window win;
- int fdesc[2];
-};
-#else /* WANT_SKYPE_X11 */
-struct AsteriskHandles {
- HWND win32_hInit_MainWindowHandle;
- HWND win32_hGlobal_SkypeAPIWindowHandle;
- int fdesc[2];
-};
-#endif /* WANT_SKYPE_X11 */
+ AsteriskHandlesAst->skype_win = skype_win;
+ AsteriskHandlesAst->disp = disp;
+ AsteriskHandlesAst->win = win;
-/*!
- * \brief PVT structure for a skypiax interface (channel), created by skypiax_mkif
- */
-struct skypiax_pvt {
- char *name; /*!< \brief 'name' of the interface (channel) */
- int interface_state; /*!< \brief 'state' of the interface (channel) */
- struct ast_channel *owner; /*!< \brief channel we belong to, possibly NULL */
- struct skypiax_pvt *next; /*!< \brief Next interface (channel) in list */
- char context[AST_MAX_EXTENSION]; /*!< \brief default Asterisk dialplan context for this interface */
- char language[MAX_LANGUAGE]; /*!< \brief default Asterisk dialplan language for this interface */
- char exten[AST_MAX_EXTENSION]; /*!< \brief default Asterisk dialplan extension for this interface */
- int skypiax_sound_rate; /*!< \brief rate of the sound device, in Hz, eg: 8000 */
- int skypiax_sound_capt_fd; /*!< \brief file descriptor for sound capture dev */
- char callid_name[50];
- char callid_number[50];
- pthread_t controldev_thread; /*!< \brief serial control thread for this interface, running during the call */
- double playback_boost;
- double capture_boost;
- int stripmsd;
- pthread_t skype_thread;
- struct AsteriskHandles AsteriskHandlesAst;
- char skype_call_id[512];
- int skype_call_ongoing;
- char skype_friends[4096];
- char skype_fullname[512];
- char skype_displayname[512];
- int skype_callflow; /*!< \brief 'callflow' of the skype interface (as opposed to phone interface) */
- int skype; /*!< \brief config flag, bool, Skype support on this interface (0 if false, -1 if true) */
- int control_to_send;
- int audiopipe[2];
- int audioskypepipe[2];
- pthread_t tcp_srv_thread;
- pthread_t tcp_cli_thread;
- short audiobuf[160];
- int audiobuf_is_loaded;
+ snprintf(buf, SKYPE_X11_BUF_SIZE, "NAME skypiax");
- //int phonebook_listing;
- //int phonebook_querying;
- //int phonebook_listing_received_calls;
+ if (!skypiax_skype_send_message(AsteriskHandlesAst, buf)) {
+ ERRORA
+ ("Sending message failed - probably Skype crashed. Please run/restart Skype manually and launch Skypiax again\n",
+ SKYPIAX_P_LOG);
+ p->skype = 0;
+ p->skype_thread = AST_PTHREADT_NULL;
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return NULL;
+ }
- //int phonebook_first_entry;
- //int phonebook_last_entry;
- //int phonebook_number_lenght;
- //int phonebook_text_lenght;
- FILE *phonebook_writing_fp;
- int skypiax_dir_entry_extension_prefix;
+ snprintf(buf, SKYPE_X11_BUF_SIZE, "PROTOCOL 6");
+ if (!skypiax_skype_send_message(AsteriskHandlesAst, buf)) {
+ ERRORA
+ ("Sending message failed - probably Skype crashed. Please run/restart Skype manually and launch Skypiax again\n",
+ SKYPIAX_P_LOG);
+ p->skype = 0;
+ p->skype_thread = AST_PTHREADT_NULL;
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return NULL;
+ }
-};
-/* FUNCTIONS */
+ /* perform an events loop */
+ XEvent an_event;
+ char buf[21]; /* can't be longer */
+ char buffer[17000];
+ char *b;
+ int i;
-/* module helpers functions */
-int load_module(void);
-int unload_module(void);
-int usecount(void);
-char *description(void);
-char *key(void);
+ b = buffer;
-/* chan_skypiax internal functions */
-void skypiax_unlocka_log(void *x);
+ while (1) {
+ pthread_testcancel();
+ XNextEvent(disp, &an_event);
+ switch (an_event.type) {
+ case ClientMessage:
-void *do_skype_thread(void *data);
-//int skypiax2skype(struct ast_channel *c, void *data);
-//int skype2skypiax(struct ast_channel *c, void *data);
-//void skypiax_skype_disconnect(void);
-int skypiax_skype_write(struct skypiax_pvt *p, char *msg_to_skype);
-int skypiax_skype_read(struct skypiax_pvt *p);
-int skypiax_console_skype(int fd, int argc, char *argv[]);
-#ifdef WANT_SKYPE_X11
-int X11_errors_handler(Display * dpy, XErrorEvent * err);
-int skypiax_skype_send_message(struct AsteriskHandles *AsteriskHandlesAst,
- const char *message_P);
-int skypiax_skype_present(Display * disp);
-void skypiax_skype_clean_disp(void *data);
-#endif /* WANT_SKYPE_X11 */
-#ifdef __CYGWIN__
-int win32_Initialize_CreateWindowClass(void);
-void win32_DeInitialize_DestroyWindowClass(void);
-int win32_Initialize_CreateMainWindow(void);
-void win32_DeInitialize_DestroyMainWindow(void);
-#endif /* __CYGWIN__ */
+ if (an_event.xclient.format != 8)
+ break;
+
+ for (i = 0; i < 20 && an_event.xclient.data.b[i] != '\0'; ++i)
+ buf[i] = an_event.xclient.data.b[i];
+
+ buf[i] = '\0';
+
+ //NOTICA("ClientMessage buf:|||%s||| buffer:|||%s||| serial=%ld|||\r\n",SKYPIAX_P_LOG,buf, buffer,an_event.xclient.serial);
+ //NOTICA ("SKYPE read: |||%s|||%d\n", SKYPIAX_P_LOG, buf, strlen(buf));
+ //NOTICA ("SKYPE buffer: |||%s|||%d\n", SKYPIAX_P_LOG, buffer, strlen(buffer));
+
+ strcat(buffer, buf);
+
+ if (i < 20) { /* last fragment */
+ write(AsteriskHandlesAst->fdesc[1], b, strlen(b) + 1);
+ //write(AsteriskHandlesAst->fdesc[1], "\0", 1);
+ DEBUGA_SKYPE("SKYPE pipewrite: |||%s|||len=%d serial=%ld\n", SKYPIAX_P_LOG, b,
+ strlen(b) + 1, an_event.xclient.serial);
+ //usleep(1000);
+ memset(buffer, '\0', 17000);
+ }
+
+ break;
+ default:
+ break;
+ }
+ }
+ } else {
+ ERRORA
+ ("Skype is not running, maybe crashed. Please run/restart Skype and relaunch Skypiax\n",
+ SKYPIAX_P_LOG);
+ p->skype = 0;
+ p->skype_thread = AST_PTHREADT_NULL;
+ return NULL;
+ }
+ p->skype = 0;
+ p->skype_thread = AST_PTHREADT_NULL;
+ pthread_cleanup_pop(1);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return NULL;
-/* CHAN_SKYPIAX.C */
-int skypiax_queue_control(struct ast_channel *chan, int control);
-struct skypiax_pvt *skypiax_console_find_desc(char *dev);
-int skypiax_serial_call(struct skypiax_pvt *p, char *dstr);
+}
-/* FUNCTIONS */
-/* PBX interface functions */
-struct ast_channel *skypiax_request(const char *type, int format, void *data, int *cause);
-int skypiax_answer(struct ast_channel *c);
-int skypiax_hangup(struct ast_channel *c);
-int skypiax_call(struct ast_channel *c, char *idest, int timeout);
-struct ast_frame *skypiax_read(struct ast_channel *chan);
-int skypiax_write(struct ast_channel *c, struct ast_frame *f);
-int skypiax_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
-#ifndef ASTERISK_VERSION_1_4
-int skypiax_indicate(struct ast_channel *c, int cond);
-#else
-int skypiax_indicate(struct ast_channel *c, int cond, const void *data, size_t datalen);
-#endif
-int skypiax_devicestate(void *data);
-#ifdef ASTERISK_VERSION_1_4
-int skypiax_senddigit_begin(struct ast_channel *ast, char digit);
-int skypiax_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration);
-#else /* ASTERISK_VERSION_1_4 */
-int skypiax_senddigit(struct ast_channel *ast, char digit);
-#endif /* ASTERISK_VERSION_1_4 */
+#endif /* WANT_SKYPE_X11 */
-/* chan_skypiax internal functions */
+int skypiax_skype_read(struct skypiax_pvt *p)
+{
-struct skypiax_pvt *skypiax_mkif(struct ast_config *cfg, char *ctg,
- int is_first_category);
-struct ast_channel *skypiax_new(struct skypiax_pvt *p, int state, char *context);
-int skypiax_restart_monitor(void);
-void *skypiax_do_monitor(void *data);
-int skypiax_sound_boost(struct ast_frame *f, double boost);
-int skypiax_sound_init(struct skypiax_pvt *p);
-int skypiax_sound_shutdown(struct skypiax_pvt *p);
-struct ast_frame *skypiax_sound_read(struct skypiax_pvt *p);
-int skypiax_sound_write(struct skypiax_pvt *p, struct ast_frame *f);
-void *skypiax_do_controldev_thread(void *data);
-#ifdef ASTERISK_VERSION_1_6
-void skypiax_store_boost(const char *s, double *boost);
-#else
-void skypiax_store_boost(char *s, double *boost);
-#endif /* ASTERISK_VERSION_1_6 */
-int skypiax_console_set_active(int fd, int argc, char *argv[]);
-int skypiax_console_hangup(int fd, int argc, char *argv[]);
-int skypiax_console_playback_boost(int fd, int argc, char *argv[]);
-int skypiax_console_capture_boost(int fd, int argc, char *argv[]);
-int skypiax_console_skypiax(int fd, int argc, char *argv[]);
-int skypiax_console_dial(int fd, int argc, char *argv[]);
-int skypiax_skypeaudio_init(struct skypiax_pvt *p);
-struct ast_frame *skypiax_skypeaudio_read(struct skypiax_pvt *p);
-void *skypiax_do_tcp_srv_thread(void *data);
-int skypiax_skypeaudio_write(struct skypiax_pvt *p, struct ast_frame *f);
-void *skypiax_do_tcp_cli_thread(void *data);
-int skypiax_skype_call(struct skypiax_pvt *p, char *idest, int timeout);
-int skypiax_console_skypiax_dir_import(int fd, int argc, char *argv[]);
+ char read_from_pipe[4096];
+ char messaggio[4096];
+ char messaggio_2[4096];
+ char *buf, obj[512] = "", id[512] = "", prop[512] = "", value[512] = "", *where;
+ char **stringp = NULL;
+ int fd;
+ int rt;
+ fd_set fs;
+ struct timeval to;
+ int howmany, i, a;
-#endif /* _SKYPIAX_H_ */
-#endif /* SKYPIAX_H */
-#ifdef CHAN_SKYPIAX
+ if (option_debug > 100) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+ memset(read_from_pipe, 0, 4096);
+ memset(messaggio, 0, 4096);
+ memset(messaggio_2, 0, 4096);
-//indent -gnu -ts4 -br -brs -cdw -lp -ce -nbfda -npcs -nprs -npsl -nbbo -saf -sai -saw -cs -bbo -nhnl -nut -sob -l90
-#include "skypiax.h"
+ fd = p->AsteriskHandlesAst.fdesc[0];
+ FD_ZERO(&fs);
+ FD_SET(fd, &fs);
+ to.tv_usec = 100;
+ to.tv_sec = 0;
+ rt = select(fd + 1, &fs, NULL, NULL, &to);
+ if (rt > 0) {
+ howmany =
+ read(p->AsteriskHandlesAst.fdesc[0], read_from_pipe, sizeof(read_from_pipe));
-/* LOCKS */
-/*! \brief Protect the skypiax_usecnt */
-AST_MUTEX_DEFINE_STATIC(skypiax_usecnt_lock);
-/*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
- * when it's doing something critical. */
-AST_MUTEX_DEFINE_STATIC(skypiax_monlock);
-/*! \brief Protect the interfaces list */
-AST_MUTEX_DEFINE_STATIC(skypiax_iflock);
+ a = 0;
+ for (i = 0; i < howmany; i++) {
+ messaggio[a] = read_from_pipe[i];
+ a++;
-/* GLOBAL VARIABLES */
-char skypiax_console_active_array[50] = "";
-char *skypiax_console_active = skypiax_console_active_array;
-/*! \brief Count of active channels for this module */
-int skypiax_usecnt = 0;
-int skypiax_debug = 0;
-/*! \brief This is the thread for the monitor which checks for input on the channels
- * which are not currently in use. */
-pthread_t skypiax_monitor_thread = AST_PTHREADT_NULL;
-pthread_t skypiax_monitor_audio_thread = AST_PTHREADT_NULL;
+ if (read_from_pipe[i] == '\0') {
-/* CONSTANTS */
-/*! \brief Textual description for this module */
-const char skypiax_desc[] = "Skypiax, Skype Driver";
-/*! \brief Textual type for this module */
-const char skypiax_type[] = "Skypiax";
-/*! \brief Name of configuration file for this module */
-const char skypiax_config[] = "skypiax.conf";
+ if (option_debug > 1)
+ DEBUGA_SKYPE("read_skype: howmany=%d, i=%d, a=%d, |||%s||| \n", SKYPIAX_P_LOG,
+ howmany, i, a, messaggio);
-char skypiax_console_skypiax_usage[] =
- " \n" "chan_skypiax commands info\n" " \n"
- " chan_skypiax adds to Asterisk the following CLI commands:\n" " \n"
- " CLI COMMANDS:\n" " skypiax_hangup\n" " skypiax_dial\n"
- " skypiax_console\n" " skypiax_playback_boost\n"
- " skypiax_capture_boost\n" " skypiax_skype\n"
- " skypiax_dir_import\n" "\n"
- " You can type 'help [command]' to obtain more specific info on usage.\n"
- " \n";
-char skypiax_console_hangup_usage[] =
- "Usage: skypiax_hangup\n"
- " Hangs up any call currently placed on the \"current\" skypiax_console (Skypiax) channel.\n"
- " Enter 'help skypiax_console' on how to change the \"current\" skypiax_console\n";
-char skypiax_console_playback_boost_usage[] =
- "Usage: skypiax_playback_boost [value]\n"
- " Shows or set the value of boost applied to the outgoing sound (voice). Possible values are: 0 (no boost applied), -40 to 40 (negative to positive range, in db). Without specifying a value, it just shows the current value. The value is for the \"current\" skypiax_console (Skypiax) channel.\n"
- " Enter 'help skypiax_console' on how to change the \"current\" skypiax_console\n";
-char skypiax_console_capture_boost_usage[] =
- "Usage: skypiax_capture_boost [value]\n"
- " Shows or set the value of boost applied to the incoming sound (voice). Possible values are: 0 (no boost applied), -40 to 40 (negative to positive range, in db). Without specifying a value, it just shows the current value. The value is for the \"current\" skypiax_console (Skypiax) channel.\n"
- " Enter 'help skypiax_console' on how to change the \"current\" skypiax_console\n";
+#if 0 //FIXME wat's the use of this?
+ if (!strcasecmp(messaggio, "ERROR 68")) { /* not yet protocol specified,
+ just authorized */
+ NOTICA
+ ("Please give the Skype client authorization to be connected by Skypiax (and to not ask you again)\n",
+ SKYPIAX_P_LOG);
+ sleep(1);
+ skypiax_skype_write(p, "PROTOCOL 6");
+ usleep(10000);
+ }
+#endif
-char skypiax_console_dial_usage[] =
- "Usage: skypiax_dial [DTMFs]\n"
- " Dials a given DTMF string in the call currently placed on the\n"
- " \"current\" skypiax_console (Skypiax) channel.\n"
- " Enter 'help skypiax_console' on how to change the \"current\" skypiax_console\n";
+ if (!strncasecmp(messaggio, "ERROR 92 CALL", 12)) {
+ ERRORA
+ ("Skype got ERROR: |||%s|||, the number we called was not recognized\n",
+ SKYPIAX_P_LOG, messaggio);
+ p->skype_callflow = CALLFLOW_STATUS_FINISHED;
+ if (option_debug)
+ DEBUGA_SKYPE("skype_call now is DOWN\n", SKYPIAX_P_LOG);
+ p->skype_call_id[0] = '\0';
-char skypiax_console_skypiax_console_usage[] =
- "Usage: skypiax_console [interface] | [show]\n"
- " If used without a parameter, displays which interface is the \"current\"\n"
- " skypiax_console. If a device is specified, the \"current\" skypiax_console is changed to\n"
- " the interface specified.\n"
- " If the parameter is \"show\", the available interfaces are listed\n";
+ if (p->interface_state != AST_STATE_HANGUP_REQUESTED) {
+ if (option_debug > 100) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ p->interface_state = AST_STATE_DOWN;
+ if(p->owner)
+ p->owner->hangupcause = AST_CAUSE_NORMAL;
+ return CALLFLOW_INCOMING_HANGUP;
+ } else {
+ p->interface_state = AST_STATE_DOWN;
+ }
+ }
-char skypiax_console_skype_usage[] =
- "Usage: skypiax_skype [command string]\n"
- " Send the 'command string' skype_msg to the Skype client connected to the \"current\" skypiax_console (Skypiax) channel.\n"
- " Enter 'help skypiax_console' on how to change the \"current\" skypiax_console\n";
+ strncpy(messaggio_2, messaggio, sizeof(messaggio) - 1);
-char skypiax_console_skypiax_dir_import_usage[] =
- "Usage: skypiax_dir_import [add | replace]\n"
- " Write in the directoriax.conf config file all the entries found in 'Contacts' list of the Skype client connected to the \"current\" skypiax_console.\n"
- " You can choose between 'add' to the end of the directoriax.conf file, or 'replace' the whole file with this new content.\n"
- " Enter 'help skypiax_console' on how to change the \"current\" skypiax_console\n";
+ buf = messaggio;
+ stringp = &buf;
+ where = strsep(stringp, " ");
+ if (!where) {
+ WARNINGA("Skype MSG without spaces: %s\n", SKYPIAX_P_LOG, messaggio);
+ }
-/*! \brief Definition of this channel for PBX channel registration */
-const struct ast_channel_tech skypiax_tech = {
- .type = skypiax_type,
- .description = skypiax_desc,
- .capabilities = AST_FORMAT_SLINEAR,
- .requester = skypiax_request,
- .hangup = skypiax_hangup,
- .answer = skypiax_answer,
- .read = skypiax_read,
- .call = skypiax_call,
- .write = skypiax_write,
- .indicate = skypiax_indicate,
- .fixup = skypiax_fixup,
- .devicestate = skypiax_devicestate,
-#ifdef ASTERISK_VERSION_1_4
- .send_digit_begin = skypiax_senddigit_begin,
- .send_digit_end = skypiax_senddigit_end,
-#else /* ASTERISK_VERSION_1_4 */
- .send_digit = skypiax_senddigit,
-#endif /* ASTERISK_VERSION_1_4 */
-};
+ if (!strcasecmp(messaggio, "#333")) {
+ /* DEBUGA_SKYPE("Skype MSG: messaggio_2: %s, messaggio2[11]: %s\n", SKYPIAX_P_LOG,
+ * messaggio_2, &messaggio_2[11]); */
+ memset(p->skype_friends, 0, 4096);
+ strncpy(p->skype_friends, &messaggio_2[11], 4095);
+ }
+ if (!strcasecmp(messaggio, "#222")) {
+ /* DEBUGA_SKYPE("Skype MSG: messaggio_2: %s, messaggio2[10]: %s\n", SKYPIAX_P_LOG,
+ * messaggio_2, &messaggio_2[10]); */
+ memset(p->skype_fullname, 0, 512);
+ strncpy(p->skype_fullname, &messaggio_2[10], 511);
+ }
+ if (!strcasecmp(messaggio, "#765")) {
+ /* DEBUGA_SKYPE("Skype MSG: messaggio_2: %s, messaggio2[10]: %s\n", SKYPIAX_P_LOG,
+ * messaggio_2, &messaggio_2[10]); */
+ memset(p->skype_displayname, 0, 512);
+ strncpy(p->skype_displayname, &messaggio_2[10], 511);
+ }
+ if (!strcasecmp(messaggio, "ERROR")) {
+ ERRORA
+ ("Skype got ERROR: |||%s|||\n",
+ SKYPIAX_P_LOG, messaggio);
+ p->skype_callflow = CALLFLOW_STATUS_FINISHED;
+ if (option_debug)
+ DEBUGA_SKYPE("skype_call now is DOWN\n", SKYPIAX_P_LOG);
+ p->skype_call_id[0] = '\0';
-/*! \brief fake skypiax_pvt structure values,
- * just for logging purposes */
-struct skypiax_pvt skypiax_log_struct = {
- .name = "none",
-};
+ if (p->interface_state != AST_STATE_HANGUP_REQUESTED) {
+ if (option_debug > 100) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ p->interface_state = AST_STATE_DOWN;
+ if(p->owner){
+ p->owner->hangupcause = AST_CAUSE_NORMAL;
+ }
+ return CALLFLOW_INCOMING_HANGUP;
+ } else {
+ p->interface_state = AST_STATE_DOWN;
+ }
+ }
+ if (!strcasecmp(messaggio, "CALL")) {
-/*! \brief Default skypiax_pvt structure values,
- * used by skypiax_mkif to initialize the interfaces */
-struct skypiax_pvt skypiax_default = {
- .interface_state = AST_STATE_DOWN,
- .skype_callflow = 0,
- .context = "default",
- .language = "en",
- .exten = "s",
- .next = NULL,
- .owner = NULL,
- .controldev_thread = AST_PTHREADT_NULL,
- .skypiax_sound_rate = 8000,
- .skypiax_sound_capt_fd = -1,
- .capture_boost = 0,
- .playback_boost = 0,
- .stripmsd = 0,
- .skype = 0,
- .skypiax_dir_entry_extension_prefix = 6,
-};
+ strncpy(obj, where, sizeof(obj) - 1);
-/*!
- * \brief PVT structure for a skypiax interface (channel), created by skypiax_mkif
- */
-struct skypiax_pvt *skypiax_iflist = NULL;
+ where = strsep(stringp, " ");
-struct ast_cli_entry myclis[] = {
- {{"skypiax_hangup", NULL}, skypiax_console_hangup,
- "Hangup a call on the skypiax_console",
- skypiax_console_hangup_usage},
- {{"skypiax_playback_boost", NULL}, skypiax_console_playback_boost, "playback boost",
- skypiax_console_playback_boost_usage},
- {{"skypiax_capture_boost", NULL}, skypiax_console_capture_boost, "capture boost",
- skypiax_console_capture_boost_usage},
- {{"skypiax_usage", NULL}, skypiax_console_skypiax, "chan_skypiax commands info",
- skypiax_console_skypiax_usage},
- {{"skypiax_skype", NULL}, skypiax_console_skype, "Skype msg",
- skypiax_console_skype_usage},
- {{"skypiax_dial", NULL}, skypiax_console_dial,
- "Dial an extension on the skypiax_console",
- skypiax_console_dial_usage},
- {{"skypiax_console", NULL}, skypiax_console_set_active,
- "Sets/displays active skypiax_console",
- skypiax_console_skypiax_console_usage},
- {{"skypiax_dir_import", NULL}, skypiax_console_skypiax_dir_import,
- "Write the directoriax.conf file, used by directoriax app",
- skypiax_console_skypiax_dir_import_usage},
-};
+ strncpy(id, where, sizeof(id) - 1);
-/* IMPLEMENTATION */
+ where = strsep(stringp, " ");
-void skypiax_unlocka_log(void *x)
-{
- ast_mutex_t *y;
- y = x;
- int i;
+ strncpy(prop, where, sizeof(prop) - 1);
- for (i = 0; i < 5; i++) { //let's be generous
+ where = strsep(stringp, " ");
- ast_log(LOG_DEBUG,
- SKYPIAX_SVN_VERSION
- "[%-7lx] I'm a dying thread, and I'm to go unlocking mutex %p for the %dth time\n",
- (unsigned long int) pthread_self(), y, i);
+ strncpy(value, where, sizeof(value) - 1);
- ast_mutex_unlock(y);
- }
- ast_log(LOG_DEBUG,
- SKYPIAX_SVN_VERSION
- "[%-7lx] I'm a dying thread, I've finished unlocking mutex %p\n",
- (unsigned long int) pthread_self(), y);
-}
+ where = strsep(stringp, " ");
-int skypiax_queue_control(struct ast_channel *c, int control)
-{
- struct skypiax_pvt *p = c->tech_pvt;
+ if (option_debug > 1)
+ DEBUGA_SKYPE
+ ("Skype MSG: messaggio: %s, obj: %s, id: %s, prop: %s, value: %s,where: %s!\n",
+ SKYPIAX_P_LOG, messaggio, obj, id, prop, value, where ? where : "NULL");
- if (option_debug > 10) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- }
-/* queue the frame */
- if (p)
- p->control_to_send = control;
- else {
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return 0;
- }
- DEBUGA_PBX("Queued CONTROL FRAME %d\n", SKYPIAX_P_LOG, control);
+ if (!strcasecmp(prop, "PARTNER_HANDLE")) {
+ strncpy(p->callid_number, value, sizeof(p->callid_number) - 1);
+ return CALLFLOW_INCOMING_RING;
+ }
+ if (!strcasecmp(prop, "PARTNER_DISPNAME")) {
+ snprintf(p->callid_name, sizeof(p->callid_name) - 1, "%s%s%s", value,
+ where ? " " : "", where ? where : "");
+ }
+ if (!strcasecmp(prop, "CONF_ID") && !strcasecmp(value, "0")) {
+ DEBUGA_SKYPE("the skype_call %s is NOT a conference call\n", SKYPIAX_P_LOG,
+ id);
+ if (p->interface_state == AST_STATE_DOWN)
+ p->interface_state = AST_STATE_PRERING;
+ }
+ if (!strcasecmp(prop, "CONF_ID") && strcasecmp(value, "0")) {
+ DEBUGA_SKYPE("the skype_call %s is a conference call\n", SKYPIAX_P_LOG, id);
+ if (p->interface_state == AST_STATE_DOWN)
+ p->interface_state = AST_STATE_PRERING;
+ }
-/* wait for the frame to be sent */
- while (p->control_to_send)
- usleep(1);
+ if (!strcasecmp(prop, "DTMF")) {
+ struct ast_frame f2 = { AST_FRAME_DTMF, value[0], };
+ DEBUGA_SKYPE("Call %s received a DTMF: %s\n", SKYPIAX_P_LOG, id, value);
+ ast_queue_frame(p->owner, &f2);
+ }
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return 0;
-}
+ if (!strcasecmp(prop, "FAILUREREASON")) {
+ /* if (option_debug > 1) */
+ DEBUGA_SKYPE
+ ("Skype has FAILED on skype_call %s. Let's wait for the FAILED message.\n",
+ SKYPIAX_P_LOG, id);
+ }
+ if (!strcasecmp(prop, "DURATION") && (!strcasecmp(value, "1"))) {
+ if (strcasecmp(id, p->skype_call_id)) {
+ strncpy(p->skype_call_id, id, sizeof(p->skype_call_id) - 1);
+ if (option_debug > 1)
+ DEBUGA_SKYPE
+ ("We called a Skype contact and he answered us on skype_call: %s.\n",
+ SKYPIAX_P_LOG, id);
+ }
+ }
-int skypiax_devicestate(void *data)
-{
- struct skypiax_pvt *p = NULL;
- char *name = data;
- int res = AST_DEVICE_INVALID;
- if (option_debug > 10) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- }
- if (!data) {
- ERRORA("Devicestate requested with no data\n", SKYPIAX_P_LOG);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return res;
- }
+ if (!strcasecmp(prop, "STATUS")) {
- /* lock the interfaces' list */
- LOKKA(&skypiax_iflock);
- /* make a pointer to the first interface in the interfaces list */
- p = skypiax_iflist;
- /* Search for the requested interface and verify if is unowned */
- while (p) {
- size_t length = strlen(p->name);
- /* is this the requested interface? */
- if (strncmp(name, p->name, length) == 0) {
- /* is this interface unowned? */
- if (!p->owner) {
- res = AST_DEVICE_NOT_INUSE;
- DEBUGA_PBX("Interface is NOT OWNED by a channel\n", SKYPIAX_P_LOG);
- } else {
- /* interface owned by a channel */
- res = AST_DEVICE_INUSE;
- DEBUGA_PBX("Interface is OWNED by a channel\n", SKYPIAX_P_LOG);
- }
+ if (!strcasecmp(value, "RINGING")) {
+ char msg_to_skype[1024];
+ if (p->interface_state != AST_STATE_DIALING) {
+ /* we are not calling out */
- /* we found the requested interface, bail out from the while loop */
- break;
- }
- /* not yet found, next please */
- p = p->next;
- }
- /* unlock the interfaces' list */
- UNLOCKA(&skypiax_iflock);
+ if (!p->owner) {
+ /* we are not inside an active call */
+ p->skype_callflow = CALLFLOW_STATUS_RINGING;
+ p->interface_state = AST_STATE_RING;
+ /* no owner, no active call, let's answer */
+ skypiax_skype_write(p, "SET AGC OFF");
+ usleep(10000);
+ skypiax_skype_write(p, "SET AEC OFF");
+ usleep(10000);
+ sprintf(msg_to_skype, "GET CALL %s PARTNER_DISPNAME", id);
+ skypiax_skype_write(p, msg_to_skype);
+ usleep(10000);
+ sprintf(msg_to_skype, "GET CALL %s PARTNER_HANDLE", id);
+ skypiax_skype_write(p, msg_to_skype);
+ usleep(10000);
+ sprintf(msg_to_skype, "ALTER CALL %s ANSWER", id);
+ skypiax_skype_write(p, msg_to_skype);
+ if (option_debug)
+ DEBUGA_SKYPE("We answered a Skype RING on skype_call %s\n",
+ SKYPIAX_P_LOG, id);
+ strncpy(p->skype_call_id, id, sizeof(p->skype_call_id) - 1);
+ } else {
+ /* we're owned, we're in a call, let's refuse */
+ sprintf(msg_to_skype, "SET CALL %s STATUS FINISHED", id);
+ skypiax_skype_write(p, msg_to_skype);
+ usleep(10000);
+ DEBUGA_SKYPE
+ ("We have NOT answered a Skype RING on skype_call %s, because we are already in a skypiax call\n",
+ SKYPIAX_P_LOG, id);
+
+ }
+ } else {
+ /* we are calling out */
+ p->skype_callflow = CALLFLOW_STATUS_RINGING;
+ p->interface_state = AST_STATE_RINGING;
+ ast_queue_control(p->owner, AST_CONTROL_RINGING);
+ strncpy(p->skype_call_id, id, sizeof(p->skype_call_id) - 1);
+ DEBUGA_SKYPE("Our remote party in skype_call %s is RINGING\n",
+ SKYPIAX_P_LOG, id);
+ }
+ } else if (!strcasecmp(value, "EARLYMEDIA")) {
+ p->skype_callflow = CALLFLOW_STATUS_EARLYMEDIA;
+ p->interface_state = AST_STATE_DIALING;
+ ast_queue_control(p->owner, AST_CONTROL_RINGING);
+ DEBUGA_SKYPE("Our remote party in skype_call %s is EARLYMEDIA\n",
+ SKYPIAX_P_LOG, id);
+ } else if (!strcasecmp(value, "MISSED")) {
+ DEBUGA_SKYPE("We missed skype_call %s\n", SKYPIAX_P_LOG, id);
+
+ } else if (!strcasecmp(value, "FINISHED")) {
+ p->skype_callflow = CALLFLOW_STATUS_FINISHED;
+ if (option_debug)
+ DEBUGA_SKYPE("skype_call %s now is DOWN\n", SKYPIAX_P_LOG, id);
+ p->skype_call_id[0] = '\0';
- if (res == AST_DEVICE_INVALID) {
- ERRORA("Checking device state for interface [%s] returning AST_DEVICE_INVALID\n",
- SKYPIAX_P_LOG, name);
- }
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return res;
-}
+ if (p->interface_state != AST_STATE_HANGUP_REQUESTED) {
+ if (option_debug > 100) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ p->interface_state = AST_STATE_DOWN;
+ if(p->owner)
+ p->owner->hangupcause = AST_CAUSE_NORMAL;
+ return CALLFLOW_INCOMING_HANGUP;
+ } else {
+ p->interface_state = AST_STATE_DOWN;
+ }
-#ifndef ASTERISK_VERSION_1_4
-int skypiax_indicate(struct ast_channel *c, int cond)
-#else
-int skypiax_indicate(struct ast_channel *c, int cond, const void *data, size_t datalen)
-#endif
-{
- struct skypiax_pvt *p = c->tech_pvt;
- int res = 0;
+ } else if (!strcasecmp(value, "CANCELLED")) {
+ p->skype_callflow = CALLFLOW_STATUS_CANCELLED;
+ if (option_debug)
+ DEBUGA_SKYPE
+ ("we tried to call Skype on skype_call %s and Skype has now CANCELLED\n",
+ SKYPIAX_P_LOG, id);
+ p->skype_call_id[0] = '\0';
- if (option_debug > 10) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- }
- NOTICA("Let's INDICATE %d\n", SKYPIAX_P_LOG, cond);
+ if (p->interface_state != AST_STATE_HANGUP_REQUESTED) {
+ if (option_debug > 100) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ p->interface_state = AST_STATE_DOWN;
+ if(p->owner)
+ p->owner->hangupcause = AST_CAUSE_NORMAL;
+ return CALLFLOW_INCOMING_HANGUP;
+ } else {
+ p->interface_state = AST_STATE_DOWN;
+ }
+ } else if (!strcasecmp(value, "FAILED")) {
+ p->skype_callflow = CALLFLOW_STATUS_FAILED;
+ if (option_debug)
+ DEBUGA_SKYPE
+ ("we tried to call Skype on skype_call %s and Skype has now FAILED\n",
+ SKYPIAX_P_LOG, id);
+ p->skype_call_id[0] = '\0';
+ strncpy(p->skype_call_id, id, sizeof(p->skype_call_id) - 1);
+ p->interface_state = AST_STATE_DOWN;
+ if (option_debug > 100) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ if(p->owner)
+ p->owner->hangupcause = AST_CAUSE_NORMAL;
+ return CALLFLOW_INCOMING_HANGUP;
+ } else if (!strcasecmp(value, "REFUSED")) {
+ if (!strcasecmp(id, p->skype_call_id)) {
+ /* this is the id of the call we are in, probably we generated it */
+ p->skype_callflow = CALLFLOW_STATUS_REFUSED;
+ if (option_debug)
+ DEBUGA_SKYPE
+ ("we tried to call Skype on skype_call %s and Skype has now REFUSED\n",
+ SKYPIAX_P_LOG, id);
+ strncpy(p->skype_call_id, id, sizeof(p->skype_call_id) - 1);
+ p->interface_state = AST_STATE_DOWN;
+ p->skype_call_id[0] = '\0';
+ if (option_debug > 100) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ if(p->owner)
+ p->owner->hangupcause = AST_CAUSE_NORMAL;
+ return CALLFLOW_INCOMING_HANGUP;
+ } else {
+ /* we're here because were us that refused an incoming call */
+ DEBUGA_SKYPE("we REFUSED skype_call %s\n", SKYPIAX_P_LOG, id);
- switch (cond) {
- case AST_CONTROL_BUSY:
- case AST_CONTROL_CONGESTION:
- case AST_CONTROL_RINGING:
- case -1:
- res = -1; /* Ask for inband indications */
- break;
- case AST_CONTROL_PROGRESS:
- case AST_CONTROL_PROCEEDING:
- case AST_CONTROL_VIDUPDATE:
- case AST_CONTROL_HOLD:
- case AST_CONTROL_UNHOLD:
-#ifdef ASTERISK_VERSION_1_4
- case AST_CONTROL_SRCUPDATE:
-#endif /* ASTERISK_VERSION_1_4 */
- break;
- default:
- WARNINGA("Don't know how to display condition %d on %s\n", SKYPIAX_P_LOG, cond,
- c->name);
- /* The core will play inband indications for us if appropriate */
- res = -1;
- }
+ }
+ } else if (!strcasecmp(value, "ROUTING")) {
+ p->skype_callflow = CALLFLOW_STATUS_ROUTING;
+ p->interface_state = AST_STATE_DIALING;
+ strncpy(p->skype_call_id, id, sizeof(p->skype_call_id) - 1);
+ DEBUGA_SKYPE("skype_call: %s is now ROUTING\n", SKYPIAX_P_LOG, id);
+ } else if (!strcasecmp(value, "UNPLACED")) {
+ p->skype_callflow = CALLFLOW_STATUS_UNPLACED;
+ p->interface_state = AST_STATE_DIALING;
+ strncpy(p->skype_call_id, id, sizeof(p->skype_call_id) - 1);
+ DEBUGA_SKYPE("skype_call: %s is now UNPLACED\n", SKYPIAX_P_LOG, id);
+ } else if (!strcasecmp(value, "INPROGRESS")) {
+ p->skype_callflow = CALLFLOW_STATUS_INPROGRESS;
+ strncpy(p->skype_call_id, id, sizeof(p->skype_call_id) - 1);
+ p->interface_state = AST_STATE_UP;
+ if (option_debug > 1)
+ DEBUGA_SKYPE("skype_call: %s is now active\n", SKYPIAX_P_LOG, id);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return res;
-}
+ if (p->owner) {
+ ast_queue_control(p->owner, AST_CONTROL_ANSWER);
+ }
+ if (option_debug > 1)
+ DEBUGA_SKYPE("skype_call: %s AST_CONTROL_ANSWER sent\n", SKYPIAX_P_LOG,
+ id);
-/*! \brief PBX interface function -build skypiax pvt structure
- * skypiax calls initiated by the PBX arrive here */
-struct ast_channel *skypiax_request(const char *type, int format, void *data, int *cause)
-{
- struct skypiax_pvt *p = NULL;
- struct ast_channel *tmp = NULL;
- char *name = data;
+ if (p->owner) {
+ char msg_to_skype[1024];
+ if (!p->tcp_cli_thread) {
+ if (ast_pthread_create
+ (&p->tcp_cli_thread, NULL, skypiax_do_tcp_cli_thread, p) < 0) {
+ ERRORA("Unable to start tcp_cli_thread thread.\n", SKYPIAX_P_LOG);
+ if (option_debug > 100) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return -1;
+ } else {
+ DEBUGA_SKYPE("started tcp_cli_thread thread.\n", SKYPIAX_P_LOG);
+ }
+ }
- if (option_debug > 10) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- }
+ usleep(100000);
+ sprintf(msg_to_skype, "ALTER CALL %s SET_OUTPUT PORT=\"5556\"", id);
+ skypiax_skype_write(p, msg_to_skype);
+ usleep(100000);
+ sprintf(msg_to_skype, "ALTER CALL %s SET_INPUT PORT=\"5558\"", id);
+ skypiax_skype_write(p, msg_to_skype);
+ usleep(100000);
+ }
- DEBUGA_PBX("Try to request type: %s, name: %s, cause: %d," " format: %d\n",
- SKYPIAX_P_LOG, type, name, *cause, format);
+ p->skype_callflow = AST_STATE_UP;
+ } else {
+ WARNINGA("skype_call: %s, STATUS: %s is not recognized\n", SKYPIAX_P_LOG,
+ id, value);
- if (!data) {
- ERRORA("Channel requested with no data\n", SKYPIAX_P_LOG);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return NULL;
- }
+ }
+ } //STATUS
- /* lock the interfaces' list */
- LOKKA(&skypiax_iflock);
- /* make a pointer to the first interface in the interfaces list */
- p = skypiax_iflist;
- /* Search for the requested interface and verify if is unowned and format compatible */
- //TODO implement groups a la chan_zap
- while (p) {
- size_t length = strlen(p->name);
- /* is this the requested interface? */
- if (strncmp(name, p->name, length) == 0) {
- /* is the requested format supported by this interface? */
- if ((format & AST_FORMAT_SLINEAR) != 0) {
- /* is this interface unowned? */
- if (!p->owner) {
- DEBUGA_PBX("Requesting: %s, name: %s, format: %d\n", SKYPIAX_P_LOG, type, name,
- format);
- /* create a new channel owning this interface */
- tmp = skypiax_new(p, AST_STATE_DOWN, p->context);
- if (!tmp) {
- /* the channel was not created, probable memory allocation error */
- *cause = AST_CAUSE_SWITCH_CONGESTION;
- }
- } else {
- /* interface owned by another channel */
- WARNINGA("owned by another channel\n", SKYPIAX_P_LOG);
- *cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
- }
- } else {
- /* requested format not supported */
- WARNINGA("format %d not supported\n", SKYPIAX_P_LOG, format);
- *cause = AST_CAUSE_BEARERCAPABILITY_NOTAVAIL;
- }
- /* we found the requested interface, bail out from the while loop */
- break;
- }
- /* not yet found, next please */
- p = p->next;
- }
- /* unlock the interfaces' list */
- UNLOCKA(&skypiax_iflock);
- /* restart the monitor so it will watch only the remaining unowned interfaces */
- skypiax_restart_monitor();
- if (tmp == NULL) {
- /* new channel was not created */
- WARNINGA("Unable to create new Skypiax channel %s\n", SKYPIAX_P_LOG, name);
- }
- /* return the newly created channel */
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return tmp;
-}
+ } //CALL
-/*! \brief Hangup skypiax call
- * Part of PBX interface, called from ast_hangup */
+ a = 0;
+ } //message end
+ } //read_from_pipe
-int skypiax_hangup(struct ast_channel *c)
-{
- struct skypiax_pvt *p;
+ }
- /* get our skypiax pvt interface from channel */
- p = c->tech_pvt;
- /* if there is not skypiax pvt why we are here ? */
- if (!p) {
- ERRORA("Asked to hangup channel not connected\n", SKYPIAX_P_LOG);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return 0;
+ if (option_debug > 100) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
}
+ return 0;
+}
- if (option_debug > 10) {
+int skypiax_skype_write(struct skypiax_pvt *p, char *msg_to_skype)
+{
+#ifdef __CYGWIN__
+ static char acInputRow[1024];
+ COPYDATASTRUCT oCopyData;
+
+ if (option_debug > 100) {
DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
}
- if (p->skype && p->interface_state != AST_STATE_DOWN) {
- char msg_to_skype[1024];
- p->interface_state = AST_STATE_HANGUP_REQUESTED;
- DEBUGA_SKYPE("hanging up skype call: %s\n", SKYPIAX_P_LOG, p->skype_call_id);
- //sprintf(msg_to_skype, "SET CALL %s STATUS FINISHED", p->skype_call_id);
- sprintf(msg_to_skype, "ALTER CALL %s HANGUP", p->skype_call_id);
- skypiax_skype_write(p, msg_to_skype);
+ sprintf(acInputRow, "%s", msg_to_skype);
+ if (option_debug > 1)
+ DEBUGA_SKYPE("acInputRow: |||%s||||\n", SKYPIAX_P_LOG, acInputRow);
+ /* send command to skype */
+ oCopyData.dwData = 0;
+ oCopyData.lpData = acInputRow;
+ oCopyData.cbData = strlen(acInputRow) + 1;
+ if (oCopyData.cbData != 1) {
+ if (SendMessage
+ (p->AsteriskHandlesAst.win32_hGlobal_SkypeAPIWindowHandle, WM_COPYDATA,
+ (WPARAM) p->AsteriskHandlesAst.win32_hInit_MainWindowHandle,
+ (LPARAM) & oCopyData) == FALSE) {
+ ERRORA
+ ("Sending message failed - probably Skype crashed.\n\nPlease shutdown Skypiax (Asterisk), then restart Skype from the menu, then launch Skypiax and try again.\n",
+ SKYPIAX_P_LOG);
+ p->skype = 0;
+ p->skype_thread = AST_PTHREADT_NULL;
+ if (option_debug > 100) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return -1;
+ }
}
+#else /* __CYGWIN__ */
+#ifdef WANT_SKYPE_X11
+ struct AsteriskHandles *AsteriskHandlesAst;
- while (p->interface_state != AST_STATE_DOWN) {
- usleep(10000);
+ if (option_debug > 100) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
}
- DEBUGA_SKYPE("Now is really DOWN\n", SKYPIAX_P_LOG);
- /* shutdown the serial monitoring thread */
- if (p->controldev_thread && (p->controldev_thread != AST_PTHREADT_NULL)
- && (p->controldev_thread != AST_PTHREADT_STOP)) {
- if (pthread_cancel(p->controldev_thread)) {
- ERRORA("controldev_thread pthread_cancel failed, maybe he killed himself?\n",
- SKYPIAX_P_LOG);
- }
- /* push it, maybe is stuck in a select or so */
- if (pthread_kill(p->controldev_thread, SIGURG)) {
- DEBUGA_SERIAL("controldev_thread pthread_kill failed, no problem\n", SKYPIAX_P_LOG);
- }
-#ifndef __CYGWIN__ /* under cygwin, this seems to be not reliable, get stuck at times */
- /* wait for it to die */
- if (pthread_join(p->controldev_thread, NULL)) {
- ERRORA("controldev_thread pthread_join failed, BAD\n", SKYPIAX_P_LOG);
+ AsteriskHandlesAst = &p->AsteriskHandlesAst;
+
+ DEBUGA_SKYPE("SENDING: |||%s||||\n", SKYPIAX_P_LOG, msg_to_skype);
+
+ if (!skypiax_skype_send_message(AsteriskHandlesAst, msg_to_skype)) {
+ ERRORA
+ ("Sending message failed - probably Skype crashed.\n\nPlease shutdown Skypiax (Asterisk), then restart Skype from the menu, then launch Skypiax and try again.\n",
+ SKYPIAX_P_LOG);
+ p->skype = 0;
+ p->skype_thread = AST_PTHREADT_NULL;
+ if (option_debug > 100) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
}
-#else /* __CYGWIN__ */
-/* allow the serial thread to die */
- usleep(300000); //300msecs
+ return -1;
+ }
+#endif /* WANT_SKYPE_X11 */
#endif /* __CYGWIN__ */
+
+ if (option_debug > 100) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
}
- p->controldev_thread = AST_PTHREADT_NULL;
+ return 0;
- p->interface_state = AST_STATE_DOWN;
- p->skype_callflow = CALLFLOW_CALL_IDLE;
+}
- DEBUGA_PBX("I'll send AST_CONTROL_HANGUP\n", SKYPIAX_P_LOG);
- ast_queue_control(p->owner, AST_CONTROL_HANGUP);
- DEBUGA_PBX("I've sent AST_CONTROL_HANGUP\n", SKYPIAX_P_LOG);
+#if defined( WANT_SKYPE_X11 ) || defined( __CYGWIN__ )
+int skypiax_skype_call(struct skypiax_pvt *p, char *idest, int timeout)
+{
+ char rdest[80];
- /* subtract one to the usage count of Skypiax-type channels */
- LOKKA(&skypiax_usecnt_lock);
- skypiax_usecnt--;
- if (skypiax_usecnt < 0)
- ERRORA("Usecnt < 0???\n", SKYPIAX_P_LOG);
- UNLOCKA(&skypiax_usecnt_lock);
- ast_update_use_count();
+ if (option_debug > 10) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
- /* our skypiax pvt interface is no more part of a channel */
- p->owner = NULL;
- /* our channel has no more this skypiax pvt interface to manage */
- c->tech_pvt = NULL;
- /* set the channel state to DOWN, eg. available, not in active use */
- if (ast_setstate(c, AST_STATE_DOWN)) {
- ERRORA("ast_setstate failed, BAD\n", SKYPIAX_P_LOG);
+ if (!p->skype) {
if (option_debug > 10) {
DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
}
- return -1;
+ return 0;
}
-
+ strncpy(rdest, idest, sizeof(rdest) - 1);
if (option_debug)
- DEBUGA_PBX("Hanged Up\n", SKYPIAX_P_LOG);
- /* restart the monitor thread, so it can recheck which interfaces it have to watch during its loop (the interfaces that are not owned by channels) */
- if (skypiax_restart_monitor()) {
- ERRORA("skypiax_restart_monitor failed, BAD\n", SKYPIAX_P_LOG);
+ DEBUGA_SKYPE("Calling Skype, rdest is: %s\n", SKYPIAX_P_LOG, rdest);
+ //skypiax_skype_write(p, "GET AGC");
+ //usleep(10000);
+ skypiax_skype_write(p, "SET AGC OFF");
+ usleep(10000);
+ //skypiax_skype_write(p, "GET AGC");
+ //usleep(10000);
+ //skypiax_skype_write(p, "GET AEC");
+ //usleep(10000);
+ skypiax_skype_write(p, "SET AEC OFF");
+ usleep(10000);
+ //skypiax_skype_write(p, "GET AEC");
+ //usleep(300000);
+
+ char msg_to_skype[1024];
+ sprintf(msg_to_skype, "CALL %s", rdest);
+ if (skypiax_skype_write(p, msg_to_skype) < 0) {
+
+ ERRORA("failed to communicate with Skype client, now exit\n", SKYPIAX_P_LOG);
if (option_debug > 10) {
DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
}
return -1;
}
+ //p->skype_call_ongoing = 1;
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
+ //if (p->owner) {
+ //ast_setstate(p->owner, AST_STATE_RINGING);
+ //}
+ ast_queue_control(p->owner, AST_CONTROL_RINGING);
return 0;
}
-/*! \brief Answer incoming call,
- * Part of PBX interface */
-int skypiax_answer(struct ast_channel *c)
+#if 0
+void skypiax_skype_disconnect(void)
{
- struct skypiax_pvt *p = c->tech_pvt;
- int res;
+ struct skypiax_pvt *p = NULL;
if (option_debug > 10) {
DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
}
- /* whle ringing, we just wait, the skype thread will answer */
- while (p->interface_state == AST_STATE_RING) {
- usleep(10000); //10msec
- }
- if (p->interface_state != AST_STATE_UP) {
- ERRORA("call answering failed\n", SKYPIAX_P_LOG);
- res = -1;
- } else {
- if (option_debug)
- DEBUGA_PBX("call answered\n", SKYPIAX_P_LOG);
- res = 0;
- }
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return res;
-}
+ if (!ast_mutex_lock(&skypiax_iflock)) {
+ /* Hangup all interfaces if they have an owner */
+ p = skypiax_iflist;
+ while (p) {
-#ifdef ASTERISK_VERSION_1_4
-int skypiax_senddigit_begin(struct ast_channel *c, char digit)
-{
- struct skypiax_pvt *p = c->tech_pvt;
- if (option_debug > 10) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- }
+ if (p->skype_thread != AST_PTHREADT_NULL) {
- DEBUGA_PBX("DIGIT BEGIN received: %c\n", SKYPIAX_P_LOG, digit);
+ if (!p->skype) {
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return;
+ }
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ DEBUGA_SKYPE("disconnecting skypiax module from skype\n", SKYPIAX_P_LOG);
+#ifdef __CYGWIN__
+ char msg_to_skype[1024];
+ sprintf(msg_to_skype, "#disconnect");
+ skypiax_skype_write(p, msg_to_skype);
+#endif /* __CYGWIN__ */
+ p->skype_call_id[0] = '\0';
+ p->skype_call_id[0] = '\0';
+ p->skype_call_ongoing = 0;
+ DEBUGA_SKYPE("TO BE killed skype_thread=%lu STOP=%lu NULL=%lu\n", SKYPIAX_P_LOG,
+ (unsigned long) p->skype_thread, (unsigned long) AST_PTHREADT_STOP,
+ (unsigned long) AST_PTHREADT_NULL);
+#ifdef __CYGWIN__
+ PostMessage(p->AsteriskHandlesAst.win32_hInit_MainWindowHandle, WM_CLOSE, 0, 0);
+ p->skype_thread = AST_PTHREADT_NULL;
+#else /* __CYGWIN__ */
+ pthread_cancel(p->skype_thread);
+ /* Nudge it a little, as it's probably stuck in select */
+ pthread_kill(p->skype_thread, SIGURG);
+ p->skype_thread = AST_PTHREADT_NULL;
+#endif /* __CYGWIN__ */
+ DEBUGA_SKYPE("KILLED skype_thread=%lu STOP=%lu NULL=%lu\n", SKYPIAX_P_LOG,
+ (unsigned long) p->skype_thread, (unsigned long) AST_PTHREADT_STOP,
+ (unsigned long) AST_PTHREADT_NULL);
+ }
+
+ p = p->next;
+ }
+ ast_mutex_unlock(&skypiax_iflock);
+ } else {
+ ERRORA("Unable to lock the interface\n", SKYPIAX_P_LOG);
}
- return 0;
+ DEBUGA_SKYPE("disconnected skypiax module from skype\n", SKYPIAX_P_LOG);
+ usleep(500);
+#ifdef WANT_SKYPE_X11
+ //system("killall -9 skype; sleep 1");
+#endif /* WANT_SKYPE_X11 */
}
+#endif
+#endif /* defined( WANT_SKYPE_X11 ) || defined( __CYGWIN__ ) */
-int skypiax_senddigit_end(struct ast_channel *c, char digit, unsigned int duration)
+#define SAMPLES_PER_FRAME 160
+int skypiax_skypeaudio_init(struct skypiax_pvt *p)
{
- struct skypiax_pvt *p = c->tech_pvt;
- char msg_to_skype[1024];
- if (option_debug > 10) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- }
-
- NOTICA("DIGIT END received: %c %d\n", SKYPIAX_P_LOG, digit, duration);
-
- sprintf(msg_to_skype, "SET CALL %s DTMF %c", p->skype_call_id, digit);
+ int c;
+/* build the pipe that will be polled on by pbx */
+ c = pipe(p->audiopipe);
+ if (c) {
+ ERRORA("Unable to create audio pipe\n", SKYPIAX_P_LOG);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return -1;
+ }
- skypiax_skype_write(p, msg_to_skype);
+/* the pipe is our audio fd for pbx to poll on */
+ p->skypiax_sound_capt_fd = p->audiopipe[0];
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ /* let's start the serial monitoring thread too, so we can have serial signaling */
+ if (ast_pthread_create(&p->tcp_srv_thread, NULL, skypiax_do_tcp_srv_thread, p) < 0) {
+ ERRORA("Unable to start tcp_srv_thread thread.\n", SKYPIAX_P_LOG);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return -1;
}
- return 0;
-}
-#else /* ASTERISK_VERSION_1_4 */
-int skypiax_senddigit(struct ast_channel *c, char digit)
-{
- struct skypiax_pvt *p = c->tech_pvt;
- char msg_to_skype[1024];
- if (option_debug > 10) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ c = pipe(p->audioskypepipe);
+ if (c) {
+ ERRORA("Unable to create audioskypepipe\n", SKYPIAX_P_LOG);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return -1;
}
- NOTICA("DIGIT received: %c\n", SKYPIAX_P_LOG, digit);
-
- sprintf(msg_to_skype, "SET CALL %s DTMF %c", p->skype_call_id, digit);
-
- skypiax_skype_write(p, msg_to_skype);
+ fcntl(p->audioskypepipe[0], F_SETFL, O_NONBLOCK);
+ fcntl(p->audioskypepipe[1], F_SETFL, O_NONBLOCK);
if (option_debug > 10) {
DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
}
return 0;
}
-
-#endif /* ASTERISK_VERSION_1_4 */
-//struct ast_frame *skypiax_skypeaudio_read(struct skypiax_pvt *p)
-#define SAMPLES_PER_FRAME 160
-/*! \brief Read audio frames from channel */
-struct ast_frame *skypiax_read(struct ast_channel *c)
+struct ast_frame *skypiax_skypeaudio_read(struct skypiax_pvt *p)
{
- struct skypiax_pvt *p = c->tech_pvt;
static struct ast_frame f;
static short __buf[SKYPIAX_FRAME_SIZE + AST_FRIENDLY_OFFSET / 2];
short *buf;
@@ -3341,15 +5379,6 @@
if (option_debug > 100) {
DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
}
-
-/* if there are control frames queued to be sent by skypiax_queue_control, send it the first */
-//TODO maybe better a real queue?
- if (p && p->owner && p->control_to_send) {
- ast_queue_control(p->owner, p->control_to_send);
- DEBUGA_PBX("Sent CONTROL FRAME %d\n", SKYPIAX_P_LOG, p->control_to_send);
- p->control_to_send = 0;
- }
-
memset(__buf, '\0', (SKYPIAX_FRAME_SIZE + AST_FRIENDLY_OFFSET / 2));
buf = __buf + AST_FRIENDLY_OFFSET / 2;
@@ -3365,14 +5394,6 @@
f.delivery.tv_sec = 0;
f.delivery.tv_usec = 0;
-/* if the call is not active (ie: answered), do not send audio frames, they would pile up in a lag queue */
- if (p->owner && p->owner->_state != AST_STATE_UP) {
- if (option_debug > 100) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return &f;
- }
-
if ((samples = read(p->audiopipe[0], buf, SAMPLES_PER_FRAME * sizeof(short))) != 320) {
DEBUGA_SOUND("read=====> NOT GOOD samples=%d expected=%d\n", SKYPIAX_P_LOG, samples,
SAMPLES_PER_FRAME * sizeof(short));
@@ -3389,3193 +5410,2837 @@
f.offset = AST_FRIENDLY_OFFSET;
f.src = skypiax_type;
f.mallocd = 0;
-
- if (p->capture_boost)
- skypiax_sound_boost(&f, p->capture_boost);
}
if (option_debug > 100) {
- DEBUGA_SOUND("samples=%d\n", SKYPIAX_P_LOG, samples);
DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
}
return &f;
}
-/*! \brief Initiate skypiax call from PBX
- * used from the dial() application
- */
-int skypiax_call(struct ast_channel *c, char *idest, int timeout)
+#define NN 160
+#define GG 160
+void *skypiax_do_tcp_srv_thread(void *data)
{
- struct skypiax_pvt *p = NULL;
- p = c->tech_pvt;
- char rdest[80], *where, dstr[100] = "";
- char *stringp = NULL;
- int status;
+ struct skypiax_pvt *p = data;
+ short in[GG];
+ short out[GG / 2];
+ int s, fd, len, sent;
+ unsigned int sin_size;
+ struct sockaddr_in my_addr;
+ struct sockaddr_in remote_addr;
+ int exit = 0;
+ int a;
+ int i;
if (option_debug > 10) {
DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
}
- if ((c->_state != AST_STATE_DOWN)
- && (c->_state != AST_STATE_RESERVED)) {
- ERRORA("skypiax_call called on %s, neither down nor reserved\n", SKYPIAX_P_LOG,
- c->name);
+ memset(&my_addr, 0, sizeof(my_addr));
+ my_addr.sin_family = AF_INET;
+ my_addr.sin_addr.s_addr = INADDR_ANY;
+ my_addr.sin_port = htons(5556);
+
+ if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ ERRORA("socket Error\n", SKYPIAX_P_LOG);
if (option_debug > 10) {
DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
}
- return -1;
+ return NULL;
}
- if (option_debug > 1)
- DEBUGA_PBX("skypiax_call to call idest: %s, timeout: %d!\n", SKYPIAX_P_LOG, idest,
- timeout);
-
- strncpy(rdest, idest, sizeof(rdest) - 1);
- stringp = rdest;
- strsep(&stringp, "/");
- where = strsep(&stringp, "/");
- if (!where) {
- ERRORA("Destination %s requires an actual destination (Skypiax/device/destination)\n",
- SKYPIAX_P_LOG, idest);
+ if (bind(s, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) < 0) {
+ ERRORA("bind Error\n", SKYPIAX_P_LOG);
if (option_debug > 10) {
DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
}
- return -1;
+ return NULL;
}
+ DEBUGA_SKYPE("started tcp_srv_thread thread.\n", SKYPIAX_P_LOG);
- strncpy(dstr, where + p->stripmsd, sizeof(dstr) - 1);
- if (option_debug > 1)
- DEBUGA_PBX("skypiax_call dialing idest: %s, timeout: %d, dstr: %s!\n", SKYPIAX_P_LOG,
- idest, timeout, dstr);
+ listen(s, 6);
- status = skypiax_skype_call(p, dstr, timeout);
- if (status) {
- WARNINGA("skypiax_call dialing failed: %d!\n", SKYPIAX_P_LOG, status);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ sin_size = sizeof(remote_addr);
+ while ((fd = accept(s, (struct sockaddr *) &remote_addr, &sin_size)) > 0) {
+ while (1) {
+ len = recv(fd, in, sizeof(short) * GG, 0);
+ if (len > 0) {
+ a = 0;
+ for (i = 0; i < len / sizeof(short); i++) {
+ out[a] = in[i];
+ i++;
+ a++;
+ }
+
+ if (!p->audiobuf_is_loaded) {
+ for (i = 0; i < (len / sizeof(short)) / 2; i++) {
+ p->audiobuf[i] = out[i];
+ }
+ p->audiobuf_is_loaded = 1;
+ } else {
+ sent = write(p->audiopipe[1], p->audiobuf, len / 2);
+ sent = write(p->audiopipe[1], out, len / 2);
+ p->audiobuf_is_loaded = 0;
+ //DEBUGA_SOUND("read=====> req=%d recv=%d to sent=%d sent=%d\n", SKYPIAX_P_LOG, sizeof(short)*GG, len, (len*sizeof(short))/2, sent);
+ }
+
+ } else if (len == 0) {
+ DEBUGA_SKYPE("client GONE\n", SKYPIAX_P_LOG);
+ break;
+ } else {
+ ERRORA("len=%d\n", SKYPIAX_P_LOG, len);
+ exit = 1;
+ break;
+ }
}
- return -1;
+ DEBUGA_SKYPE("client GONE\n", SKYPIAX_P_LOG);
+ close(fd);
+ if (exit)
+ break;
}
- if (option_debug > 1)
- DEBUGA_PBX("skypiax_call dialed idest: %s, timeout: %d, dstr: %s!\n", SKYPIAX_P_LOG,
- idest, timeout, dstr);
-
- ast_setstate(p->owner, AST_STATE_DIALING);
+ DEBUGA_SKYPE("server (I am it) GONE\n", SKYPIAX_P_LOG);
+ close(s);
if (option_debug > 10) {
DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
}
- return 0;
+ return NULL;
}
-
-int skypiax_sound_boost(struct ast_frame *f, double boost)
+void *skypiax_do_tcp_cli_thread(void *data)
{
-/* LUIGI RIZZO's magic */
- if (boost != 0) { /* scale and clip values */
- int i, x;
- int16_t *ptr = (int16_t *) f->data;
- for (i = 0; i < f->samples; i++) {
- x = (ptr[i] * boost) / BOOST_SCALE;
- if (x > 32767) {
- x = 32767;
- } else if (x < -32768) {
- x = -32768;
+ struct skypiax_pvt *p = data;
+ int s, fd, len;
+ short in[NN / 2];
+ short out[NN];
+ unsigned int sin_size;
+ struct sockaddr_in my_addr;
+ struct sockaddr_in remote_addr;
+ int a;
+ int i;
+ int got;
+
+ if (option_debug > 10) {
+ DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+ memset(&my_addr, 0, sizeof(my_addr));
+ my_addr.sin_family = AF_INET;
+ my_addr.sin_addr.s_addr = INADDR_ANY;
+ my_addr.sin_port = htons(5558);
+
+ if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ ERRORA("socket Error\n", SKYPIAX_P_LOG);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return NULL;
+ }
+
+ if (bind(s, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) < 0) {
+ ERRORA("bind Error\n", SKYPIAX_P_LOG);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
+ }
+ return NULL;
+ }
+ DEBUGA_SKYPE("started tcp_cli_thread thread.\n", SKYPIAX_P_LOG);
+
+ listen(s, 6);
+
+ sin_size = sizeof(remote_addr);
+ while ((fd = accept(s, (struct sockaddr *) &remote_addr, &sin_size)) > 0) {
+ DEBUGA_SKYPE("ACCEPTED\n", SKYPIAX_P_LOG);
+ while (1 && p->owner && p->owner->_state == AST_STATE_UP) {
+
+ got = read(p->audioskypepipe[0], in, (NN / 2) * sizeof(short));
+
+ if (got > 0) {
+ a = 0;
+ for (i = 0; i < got / sizeof(short); i++) {
+ out[a] = in[i];
+ a++;
+ out[a] = in[i];
+ a++;
+ }
+
+ len = send(fd, out, got * 2, 0);
+
+ if (len == 0) {
+ DEBUGA_SKYPE("client GONE\n", SKYPIAX_P_LOG);
+ break;
+ }
+ } else {
+ usleep(100);
}
- ptr[i] = x;
+
}
+ DEBUGA_SKYPE("client GONE\n", SKYPIAX_P_LOG);
+ close(fd);
+ }
+
+ DEBUGA_SKYPE("server (I am it) GONE\n", SKYPIAX_P_LOG);
+ close(s);
+ if (option_debug > 10) {
+ DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
}
- return 0;
+ return NULL;
}
-/*! \brief Send audio frame to channel */
-int skypiax_write(struct ast_channel *c, struct ast_frame *f)
+int skypiax_skypeaudio_write(struct skypiax_pvt *p, struct ast_frame *f)
{
- struct skypiax_pvt *p = c->tech_pvt;
int sent;
if (option_debug > 100) {
DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
}
- if (p->owner && p->owner->_state != AST_STATE_UP) {
- if (option_debug > 100) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return 0;
- }
- if (p->playback_boost)
- skypiax_sound_boost(f, p->playback_boost);
-
sent = write(p->audioskypepipe[1], (short *) f->data, f->datalen);
- //skypiax_sound_write(p, f);
if (option_debug > 100) {
- DEBUGA_SOUND("sent=%d\n", SKYPIAX_P_LOG, sent);
DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
}
return 0;
}
-
-/*! \brief Fix up a channel: If a channel is consumed, this is called.
- * Basically update any ->owner links */
-int skypiax_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
+int skypiax_console_skype(int fd, int argc, char *argv[])
{
- struct skypiax_pvt *p = newchan->tech_pvt;
+ struct skypiax_pvt *p = skypiax_console_find_desc(skypiax_console_active);
+ char skype_msg[1024];
+ int i, a, c;
+ if (argc == 1) {
+ return RESULT_SHOWUSAGE;
+ }
+ if (!p) {
+ ast_cli(fd,
+ "No \"current\" console for skypiax_skype, please enter 'help console'\n");
+ return RESULT_SUCCESS;
+ }
if (option_debug > 10) {
DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
}
- if (!p) {
- ERRORA("No pvt after masquerade. Strange things may happen\n", SKYPIAX_P_LOG);
+ if (!p->skype) {
+ ast_cli(fd, "The \"current\" console is not connected to a Skype client'\n");
if (option_debug > 10) {
DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
}
- return -1;
- }
-
- if (p->owner != oldchan) {
- ERRORA("old channel wasn't %p but was %p\n", SKYPIAX_P_LOG, oldchan, p->owner);
if (option_debug > 10) {
DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
}
- return -1;
+ return RESULT_SUCCESS;
}
- p->owner = newchan;
+ memset(skype_msg, 0, sizeof(skype_msg));
+ c = 0;
+ for (i = 1; i < argc; i++) {
+ for (a = 0; a < strlen(argv[i]); a++) {
+ skype_msg[c] = argv[i][a];
+ c++;
+ if (c == 1022)
+ break;
+ }
+ if (i != argc - 1) {
+ skype_msg[c] = ' ';
+ c++;
+ }
+ if (c == 1023)
+ break;
+ }
+ skypiax_skype_write(p, skype_msg);
if (option_debug > 10) {
DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
}
- return 0;
+ return RESULT_SUCCESS;
}
-struct ast_channel *skypiax_new(struct skypiax_pvt *p, int state, char *context)
+/* For simplicity, I'm keeping the format compatible with the voicemail config,
+ but i'm open to suggestions for isolating it */
+
+#define SKYPIAX_DIR_CONFIG "directoriax.conf"
+
+int skypiax_console_skypiax_dir_import(int fd, int argc, char *argv[])
{
- struct ast_channel *tmp;
+ //int res;
+ struct skypiax_pvt *p = skypiax_console_find_desc(skypiax_console_active);
+ //char list_command[64];
+ char fn[256];
+ char date[256] = "";
+ time_t t;
+ char *configfile = SKYPIAX_DIR_CONFIG;
+ int add_to_skypiax_dir_conf = 1;
+ //int fromskype = 0;
+ //int fromcell = 0;
- if (option_debug > 10) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+#if 0
+ if(directoriax_entry_extension){
+ skypiax_dir_entry_extension=directoriax_entry_extension;
+ }else{
+ ast_cli(fd, "No 'directoriax_entry_extension', you MUST have loaded directoriax.so\n");
+ return RESULT_SUCCESS;
}
- /* alloc a generic channel struct */
-#ifndef ASTERISK_VERSION_1_4
- tmp = ast_channel_alloc(1);
-#else
- //tmp = ast_channel_alloc(1, state, 0, 0, "", p->exten, p->context, 0, "");
- //tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "Skypiax/%s", p->name);
- tmp =
- ast_channel_alloc(1, state, 0, 0, "", p->exten, p->context, 0, "Skypiax/%s", p->name);
+#endif
-#endif /* ASTERISK_VERSION_1_4 */
- if (tmp) {
+ if (argc != 2)
+ return RESULT_SHOWUSAGE;
+ if (!p) {
+ ast_cli(fd, "No \"current\" console ???, please enter 'help skypiax_console'\n");
+ return RESULT_SUCCESS;
+ }
- /* give a name to the newly created channel */
-#ifndef ASTERISK_VERSION_1_4
- snprintf(tmp->name, sizeof(tmp->name), "Skypiax/%s", p->name);
- tmp->type = skypiax_type;
-#else /* ASTERISK_VERSION_1_4 */
- ast_string_field_build(tmp, name, "Skypiax/%s", p->name);
-#endif /* ASTERISK_VERSION_1_4 */
+ if (!strcasecmp(argv[1], "add"))
+ add_to_skypiax_dir_conf = 1;
+ else if (!strcasecmp(argv[1], "replace"))
+ add_to_skypiax_dir_conf = 0;
+ else {
+ ast_cli(fd, "\n\nYou have neither specified 'add' nor 'replace'\n\n");
+ return RESULT_SHOWUSAGE;
+ }
- DEBUGA_PBX("new channel: name=%s requested_state=%d\n", SKYPIAX_P_LOG, tmp->name,
- state);
+#if 0
+ if (!strcasecmp(argv[2], "fromskype"))
+ fromskype = 1;
+ else if (!strcasecmp(argv[2], "fromcell"))
+ fromcell = 1;
+ else {
+ ast_cli(fd, "\n\nYou have neither specified 'fromskype' nor 'fromcell'\n\n");
+ return RESULT_SHOWUSAGE;
+ }
- /* fd for the channel to poll for incoming audio */
- tmp->fds[0] = p->skypiax_sound_capt_fd;
+ if (fromcell) {
+ ast_cli(fd,
+ "Importing from cellphone is currently supported only on \"AT\" cellphones :( !\n");
+ //fclose(p->phonebook_writing_fp);
+ //skypiax_dir_create_extensions();
+ return RESULT_SUCCESS;
+ }
- /* audio formats managed */
- tmp->nativeformats = AST_FORMAT_SLINEAR;
- tmp->readformat = AST_FORMAT_SLINEAR;
- tmp->writeformat = AST_FORMAT_SLINEAR;
- /* the technology description (eg. the interface type) of the newly created channel is the Skypiax's one */
- tmp->tech = &skypiax_tech;
- /* the technology pvt (eg. the interface) of the newly created channel is this interface pvt */
- tmp->tech_pvt = p;
+ if (fromskype)
+ if (!p->skype) {
+ ast_cli(fd, "Importing from skype is supported by skypiax_dir on chan_skypiax!\n");
+ //fclose(p->phonebook_writing_fp);
+ //skypiax_dir_create_extensions();
+ return RESULT_SUCCESS;
+ }
+
+ if (fromcell || fromskype)
+ if (argc != 3) {
+ ast_cli(fd,
+ "\n\nYou don't have to specify a filename with 'fromcell' or with 'fromskype'\n\n");
+ return RESULT_SHOWUSAGE;
+ }
+#endif
+
+ /*******************************************************************************************/
+
+ if (configfile[0] == '/') {
+ ast_copy_string(fn, configfile, sizeof(fn));
+ } else {
+ snprintf(fn, sizeof(fn), "%s/%s", ast_config_AST_CONFIG_DIR, configfile);
+ }
+ if (option_debug)
+ NOTICA("Opening '%s'\n", SKYPIAX_P_LOG, fn);
+ time(&t);
+ ast_copy_string(date, ctime(&t), sizeof(date));
+
+ if (add_to_skypiax_dir_conf)
+ p->phonebook_writing_fp = fopen(fn, "a+");
+ else
+ p->phonebook_writing_fp = fopen(fn, "w+");
+
+ if (p->phonebook_writing_fp) {
+ if (add_to_skypiax_dir_conf) {
+ if (option_debug)
+ NOTICA("Opened '%s' for appending \n", SKYPIAX_P_LOG, fn);
+ fprintf(p->phonebook_writing_fp, ";!\n");
+ fprintf(p->phonebook_writing_fp, ";! Update Date: %s", date);
+ fprintf(p->phonebook_writing_fp, ";! Updated by: %s, %d\n", __FILE__, __LINE__);
+ fprintf(p->phonebook_writing_fp, ";!\n");
+ } else {
+ if (option_debug)
+ NOTICA("Opened '%s' for writing \n", SKYPIAX_P_LOG, fn);
+ fprintf(p->phonebook_writing_fp, ";!\n");
+ fprintf(p->phonebook_writing_fp, ";! Automatically generated configuration file\n");
+ fprintf(p->phonebook_writing_fp, ";! Filename: %s (%s)\n", configfile, fn);
+ fprintf(p->phonebook_writing_fp, ";! Creation Date: %s", date);
+ fprintf(p->phonebook_writing_fp, ";! Generated by: %s, %d\n", __FILE__, __LINE__);
+ fprintf(p->phonebook_writing_fp, ";!\n");
+ fprintf(p->phonebook_writing_fp, "[general]\n\n");
+ fprintf(p->phonebook_writing_fp, "[default]\n");
+ }
+
+ /*******************************************************************************************/
+ //if (fromskype) {
+ if (p->skype) {
+ WARNINGA
+ ("About to querying the Skype client 'Contacts', it may take some moments... Don't worry.\n",
+ SKYPIAX_P_LOG);
+ if (p->skype_thread != AST_PTHREADT_NULL) {
+ char msg_to_skype[1024];
+
+ p->skype_friends[0] = '\0';
+ sprintf(msg_to_skype, "#333 SEARCH FRIENDS");
+ if (skypiax_skype_write(p, msg_to_skype) < 0) {
+ return -1;
+ }
+
+ int friends_count = 0;
+ while (p->skype_friends[0] == '\0') {
+ /* FIXME needs a timeout, can't wait forever!
+ * eg. when skype is running but not connected! */
+ usleep(100);
+ friends_count++;
+ if (friends_count > 20000) {
+ return -1; /* FIXME */
+ }
+ }
+
+ }
+
+ if (p->skype_thread != AST_PTHREADT_NULL) {
+ char msg_to_skype[1024];
+
+ if (p->skype_friends[0] != '\0') {
+ char *buf, *where;
+ char **stringp;
+ int skype_dir_file_written = 0;
+
+ buf = p->skype_friends;
+ stringp = &buf;
+ where = strsep(stringp, ", ");
+ while (where) {
+ if (where[0] != '\0') {
+ /*
+ * So, we have the Skype username (the HANDLE, I think is called).
+ * But we want to call the names we see in the Skype contact list
+ * So, let's check the DISPLAYNAME (the end user modified contact name)
+ * Then, we check the FULLNAME (that appears as it was the DISPLAYNAME
+ * if the end user has not modify it)
+ * If we still have neither DISPLAYNAME nor FULLNAME, we'll use the
+ * Skipe username (the HANDLE)
+ */
- /* copy this interface default context, extension, language to the newly created channel */
- if (strlen(p->context))
- strncpy(tmp->context, p->context, sizeof(tmp->context) - 1);
- if (strlen(p->exten))
- strncpy(tmp->exten, p->exten, sizeof(tmp->exten) - 1);
-#ifndef ASTERISK_VERSION_1_4
- if (strlen(p->language))
- strncpy(tmp->language, p->language, sizeof(tmp->language) - 1);
-#else
- if (strlen(p->language))
- ast_string_field_set(tmp, language, p->language);
-#endif /* ASTERISK_VERSION_1_4 */
- /* copy the requested context (not necessarily the interface default) to the newly created channel */
- if (strlen(context))
- strncpy(tmp->context, context, sizeof(tmp->context) - 1);
+ p->skype_displayname[0] = '\0';
+ sprintf(msg_to_skype, "#765 GET USER %s DISPLAYNAME", where);
+ skypiax_skype_write(p, msg_to_skype);
+ int displayname_count = 0;
+ while (p->skype_displayname[0] == '\0') {
+ /* FIXME needs a timeout, can't wait forever!
+ * eg. when skype is running but not connected! */
+ usleep(100);
+ displayname_count++;
+ if (displayname_count > 20000)
+ return -1; /* FIXME */
+ }
+ if (p->skype_displayname[0] != '\0') {
+ char *where2;
+ char sanitized[300];
- /* copy this interface default callerid in the newly created channel */
- ast_set_callerid(tmp, !ast_strlen_zero(p->callid_number) ? p->callid_number : NULL,
- !ast_strlen_zero(p->callid_name) ? p->callid_name : NULL,
- !ast_strlen_zero(p->callid_number) ? p->callid_number : NULL);
+ sanitized[0] = '\0';
- DEBUGA_PBX("callid_number=%s, callid_name=%s\n", SKYPIAX_P_LOG, p->callid_number,
- p->callid_name);
+ where2 = strstr(p->skype_displayname, "DISPLAYNAME ");
+ if (where2) {
- /* the owner of this interface pvt is the newly created channel */
- p->owner = tmp;
- /* set the newly created channel state to the requested state */
- if (ast_setstate(tmp, state)) {
- ERRORA("ast_setstate failed, BAD\n", SKYPIAX_P_LOG);
- //ast_dsp_free(p->dsp);
- ast_channel_free(tmp);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return NULL;
- }
- /* if the requested state is different from DOWN, let the pbx manage this interface (now part of the newly created channel) */
- if (state != AST_STATE_DOWN) {
- DEBUGA_PBX("Try to start PBX on %s, state=%d\n", SKYPIAX_P_LOG, tmp->name, state);
- if (ast_pbx_start(tmp)) {
- ERRORA("Unable to start PBX on %s\n", SKYPIAX_P_LOG, tmp->name);
- ast_channel_free(tmp);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return NULL;
- }
- }
- /* let's start the serial monitoring thread too, so we can have serial signaling */
- if (ast_pthread_create(&p->controldev_thread, NULL, skypiax_do_controldev_thread, p) <
- 0) {
- ERRORA("Unable to start controldev thread.\n", SKYPIAX_P_LOG);
- ast_channel_free(tmp);
- tmp = NULL;
- }
- DEBUGA_SERIAL("STARTED controldev_thread=%lu STOP=%lu NULL=%lu\n", SKYPIAX_P_LOG,
- (unsigned long) p->controldev_thread, (unsigned long) AST_PTHREADT_STOP,
- (unsigned long) AST_PTHREADT_NULL);
+ /* there can be some *smart* that makes a displayname
+ * that is different than first<space>last, */
+ /* maybe initials, simbols, slashes,
+ * something smartish... let's check */
- /* add one to the usage count of Skypiax-type channels */
- LOKKA(&skypiax_usecnt_lock);
- skypiax_usecnt++;
- UNLOCKA(&skypiax_usecnt_lock);
- ast_update_use_count();
+ if (where2[12] != '\0') {
+ int i = 12;
+ int x = 0;
+ int spaces = 0;
+ int last_char_was_space = 0;
- /* return the newly created channel */
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return tmp;
- }
- ERRORA("failed memory allocation for Skypiax channel\n", SKYPIAX_P_LOG);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return NULL;
-}
+ for (i = 12; i < strlen(where2) && x < 299; i++) {
+ if (!isalnum(where2[i])) {
+ if (!isblank(where2[i])) {
+ /* bad char */
+ continue;
+ }
+ /* is a space */
+ if (last_char_was_space == 1) /* do not write 2 consecutive spaces */
+ continue;
+ last_char_was_space = 1;
+ sanitized[x] = ' ';
+ x++;
+ continue;
+ }
+ /* is alphanum */
+ last_char_was_space = 0;
+ sanitized[x] = where2[i];
+ x++;
+ continue;
+ }
-/*!
- * \brief Load the module into Asterisk and start its threads
- *
- * This function register the module into Asterisk,
- * create the interfaces for the channels,
- * start the auxiliary threads for the interfaces,
- * then start a monitor thread. The monitor thread
- * will signal Asterisk when an interface receive a call.
- *
- *
- * \return zero on success, -1 on error.
- */
-int load_module(void)
-{
- int i;
- struct ast_config *cfg;
- struct skypiax_pvt *tmp;
- struct skypiax_pvt *p = NULL;
-#ifdef ASTERISK_VERSION_1_6
- struct ast_flags config_flags = { 0 };
-#endif /* ASTERISK_VERSION_1_6 */
+ sanitized[x] = '\0';
+ if (spaces == 0) {
+ }
+ DEBUGA_SKYPE("sanitized=|%s|, where=|%s|, where2=|%s|\n",
+ SKYPIAX_P_LOG, sanitized, where, &where2[12]);
+ }
- if (option_debug > 10) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- ast_log(LOG_DEBUG, "ENTERING FUNC\n");
- }
-#if defined(WANT_SKYPE_X11) || defined(__CYGWIN__)
-#ifndef __CYGWIN__
- if (!XInitThreads())
- ast_log(LOG_ERROR, "Not initialized XInitThreads!\n");
-#endif /* __CYGWIN__ */
-#if 0
- ast_register_atexit(skypiax_skype_disconnect);
- ast_register_application(skype2skypiaxapp, skype2skypiax, skype2skypiaxsynopsis,
- skype2skypiaxdescrip);
- ast_register_application(skypiax2skypeapp, skypiax2skype, skypiax2skypesynopsis,
- skypiax2skypedescrip);
-#endif
-#endif /* defined(WANT_SKYPE_X11) || defined(__CYGWIN__) */
+ if (where2[12] != '\0') {
+ skypiax_dir_entry_extension++;
+ if (where[0] == '+' || isdigit(where[0])) { /* is a skypeout number */
+ fprintf(p->phonebook_writing_fp,
+ "%s => ,%sSKO,,,hidefromdir=%s|phonebook_direct_calling_ext=%d%s%.4d|phonebook_entry_fromskype=%s|phonebook_entry_owner=%s\n",
+ where, sanitized, "no",
+ p->skypiax_dir_entry_extension_prefix, "2",
+ skypiax_dir_entry_extension, "yes", "not_specified");
+ } else { /* is a skype name */
+ fprintf(p->phonebook_writing_fp,
+ "%s => ,%sSKY,,,hidefromdir=%s|phonebook_direct_calling_ext=%d%s%.4d|phonebook_entry_fromskype=%s|phonebook_entry_owner=%s\n",
+ where, sanitized, "no",
+ p->skypiax_dir_entry_extension_prefix, "1",
+ skypiax_dir_entry_extension, "yes", "not_specified");
+ }
+ skype_dir_file_written = 1;
- /* make sure we can register our channel type with Asterisk */
- i = ast_channel_register(&skypiax_tech);
- if (i < 0) {
- ERRORA("Unable to register channel type '%s'\n", SKYPIAX_P_LOG, skypiax_type);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return -1;
- }
- /* load skypiax.conf config file */
-#ifdef ASTERISK_VERSION_1_6
- cfg = ast_config_load(skypiax_config, config_flags);
-#else
- cfg = ast_config_load(skypiax_config);
-#endif /* ASTERISK_VERSION_1_6 */
- if (cfg != NULL) {
- char *ctg = NULL;
- int is_first_category = 1;
- while ((ctg = ast_category_browse(cfg, ctg)) != NULL) {
- /* create one interface for each category in skypiax.conf config file, first one set the defaults */
- tmp = skypiax_mkif(cfg, ctg, is_first_category);
- if (tmp) {
- DEBUGA_PBX
- ("Created channel Skypiax: skypiax.conf category '[%s]', channel name '%s'"
- "\n", SKYPIAX_P_LOG, ctg, tmp->name);
- /* add interface to skypiax_iflist */
- tmp->next = skypiax_iflist;
- skypiax_iflist = tmp;
- /* next one will not be the first ;) */
- if (is_first_category == 1) {
- is_first_category = 0;
- skypiax_console_active = tmp->name;
- }
- } else {
- ERRORA("Unable to create channel Skypiax from skypiax.conf category '[%s]'\n",
- SKYPIAX_P_LOG, ctg);
- /* if error, unload config from memory and return */
- ast_config_destroy(cfg);
- ast_channel_unregister(&skypiax_tech);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return -1;
- }
- /* do it for each category described in config */
- }
+ }
+ }
+ }
+ p->skype_displayname[0] = '\0';
- /* we finished, unload config from memory */
- ast_config_destroy(cfg);
- } else {
- ERRORA("Unable to load skypiax_config skypiax.conf\n", SKYPIAX_P_LOG);
- ast_channel_unregister(&skypiax_tech);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return -1;
- }
-#ifndef ASTERISK_VERSION_1_6
- ast_cli_register_multiple(myclis, sizeof(myclis) / sizeof(struct ast_cli_entry));
-#endif /* ASTERISK_VERSION_1_6 */
- /* start to monitor the interfaces (skypiax_iflist) for the first time */
- if (skypiax_restart_monitor()) {
- ERRORA("skypiax_restart_monitor failed, BAD\n", SKYPIAX_P_LOG);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return -1;
- }
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return 0;
-}
+ p->skype_fullname[0] = '\0';
+ sprintf(msg_to_skype, "#222 GET USER %s FULLNAME", where);
+ skypiax_skype_write(p, msg_to_skype);
+ int fullname_count = 0;
+ while (p->skype_fullname[0] == '\0') {
+ /* FIXME needs a timeout, can't wait forever!
+ * eg. when skype is running but not connected! */
+ usleep(100);
+ fullname_count++;
+ if (fullname_count > 20000)
+ return -1; /* FIXME */
+ }
+ if (p->skype_fullname[0] != '\0') {
+ char *where2;
+ char sanitized[300];
-/*!
- * \brief Unload the module from Asterisk and shutdown its threads
- *
- * This function unregister the module from Asterisk,
- * destroy the interfaces for the channels,
- * shutdown the auxiliary threads for the interfaces,
- * then shutdown its monitor thread.
- *
- * \return zero on success, -1 on error.
- */
-int unload_module(void)
-{
- struct skypiax_pvt *p = NULL, *p2 = NULL;
- int res;
+ where2 = strstr(p->skype_fullname, "FULLNAME ");
+ if (where2) {
- if (option_debug > 10) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- }
+ /* there can be some *smart* that makes a fullname
+ * that is different than first<space>last, */
+ /* maybe initials, simbols, slashes,
+ * something smartish... let's check */
- /* unregister our channel type with Asterisk */
- ast_channel_unregister(&skypiax_tech);
- ast_cli_unregister_multiple(myclis, sizeof(myclis) / sizeof(struct ast_cli_entry));
+ if (where2[9] != '\0') {
+ int i = 9;
+ int x = 0;
+ int spaces = 0;
+ int last_char_was_space = 0;
-#if defined(WANT_SKYPE_X11) || defined(__CYGWIN__)
-#ifndef __CYGWIN__
- //FIXME what to do? if (!XInitThreads())
- //FIXME what to do? ast_log(LOG_ERROR, "Not initialized XInitThreads!\n");
-#endif /* __CYGWIN__ */
-#if 0
- ast_unregister_atexit(skypiax_skype_disconnect);
- ast_unregister_application(skype2skypiaxapp);
- ast_unregister_application(skypiax2skypeapp);
-#endif
-#endif /* defined(WANT_SKYPE_X11) || defined(__CYGWIN__) */
+ for (i = 9; i < strlen(where2) && x < 299; i++) {
+ if (!isalnum(where2[i])) {
+ if (!isblank(where2[i])) {
+ /* bad char */
+ continue;
+ }
+ /* is a space */
+ if (last_char_was_space == 1) /* do not write 2 consecutive spaces */
+ continue;
+ last_char_was_space = 1;
+ sanitized[x] = ' ';
+ x++;
+ continue;
+ }
+ /* alphanum */
+ last_char_was_space = 0;
+ sanitized[x] = where2[i];
+ x++;
+ continue;
+ }
- /* lock the skypiax_monlock, kill the monitor thread, unlock the skypiax_monlock */
- LOKKA(&skypiax_monlock);
- if (skypiax_monitor_thread && (skypiax_monitor_thread != AST_PTHREADT_NULL)
- && (skypiax_monitor_thread != AST_PTHREADT_STOP)) {
- if (pthread_cancel(skypiax_monitor_thread)) {
- ERRORA("pthread_cancel failed, BAD\n", SKYPIAX_P_LOG);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return -1;
- }
- if (pthread_kill(skypiax_monitor_thread, SIGURG)) {
- DEBUGA_PBX("pthread_kill failed\n", SKYPIAX_P_LOG); //maybe it just died
- }
-#ifndef __CYGWIN__ /* under cygwin, this seems to be not reliable, get stuck at times */
- if (pthread_join(skypiax_monitor_thread, NULL)) {
- ERRORA("pthread_join failed, BAD\n", SKYPIAX_P_LOG);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return -1;
- }
-#endif /* __CYGWIN__ */
- }
- skypiax_monitor_thread = AST_PTHREADT_STOP;
- UNLOCKA(&skypiax_monlock);
+ sanitized[x] = '\0';
+ if (spaces == 0) {
+ }
+ DEBUGA_SKYPE("sanitized=|%s|, where=|%s|, where2=|%s|\n",
+ SKYPIAX_P_LOG, sanitized, where, &where2[9]);
+ }
- if (skypiax_monitor_audio_thread && (skypiax_monitor_audio_thread != AST_PTHREADT_NULL)
- && (skypiax_monitor_audio_thread != AST_PTHREADT_STOP)) {
+ if (skype_dir_file_written == 0) {
+ skypiax_dir_entry_extension++;
+ if (where2[9] != '\0') {
+ if (where[0] == '+' || isdigit(where[0])) { /* is a skypeout number */
+ fprintf(p->phonebook_writing_fp,
+ "%s => ,%sSKO,,,hidefromdir=%s|phonebook_direct_calling_ext=%d%s%.4d|phonebook_entry_fromskype=%s|phonebook_entry_owner=%s\n",
+ where, sanitized, "no",
+ p->skypiax_dir_entry_extension_prefix, "2",
+ skypiax_dir_entry_extension, "yes", "not_specified");
+ } else { /* is a skype name */
+ fprintf(p->phonebook_writing_fp,
+ "%s => ,%sSKY,,,hidefromdir=%s|phonebook_direct_calling_ext=%d%s%.4d|phonebook_entry_fromskype=%s|phonebook_entry_owner=%s\n",
+ where, sanitized, "no",
+ p->skypiax_dir_entry_extension_prefix, "1",
+ skypiax_dir_entry_extension, "yes", "not_specified");
- if (pthread_cancel(skypiax_monitor_audio_thread)) {
- ERRORA("pthread_cancel skypiax_monitor_audio_thread failed, BAD\n", SKYPIAX_P_LOG);
- }
- if (pthread_kill(skypiax_monitor_audio_thread, SIGURG)) {
- DEBUGA_PBX("pthread_kill skypiax_monitor_audio_thread failed, no problem\n", SKYPIAX_P_LOG); //maybe it just died
- }
+ }
- if (pthread_join(skypiax_monitor_audio_thread, NULL)) {
- ERRORA("pthread_join failed, BAD\n", SKYPIAX_P_LOG);
- }
- }
- /* lock the skypiax_iflock, and go through the interfaces list (skypiax_iflist) */
- LOKKA(&skypiax_iflock);
- p = skypiax_iflist;
- while (p) {
- /* for each interface in list */
- p2 = p->next;
- /* shutdown the sound system, close sound fds, and if exist shutdown the sound managing threads */
- DEBUGA_SOUND("shutting down sound\n", SKYPIAX_P_LOG);
- res = skypiax_sound_shutdown(p);
- if (res == -1) {
- ERRORA("Failed to shutdown sound\n", SKYPIAX_P_LOG);
- }
-#if 0
- /* if a dsp struct has been allocated, free it */
- if (p->dsp) {
- ast_dsp_free(p->dsp);
- p->dsp = NULL;
- }
-#endif
- DEBUGA_PBX("freeing PVT\n", SKYPIAX_P_LOG);
- /* free the pvt allocated memory */
- free(p);
- /* next one, please */
- p = p2;
- }
- /* finished with the interfaces list, unlock the skypiax_iflock */
- UNLOCKA(&skypiax_iflock);
+ } else {
+ if (where[0] == '+' || isdigit(where[0])) { /* is a skypeout number */
+ fprintf(p->phonebook_writing_fp,
+ "%s => ,%sSKO,,,hidefromdir=%s|phonebook_direct_calling_ext=%d%s%.4d|phonebook_entry_fromskype=%s|phonebook_entry_owner=%s\n",
+ where, where, "no",
+ p->skypiax_dir_entry_extension_prefix, "2",
+ skypiax_dir_entry_extension, "yes", "not_specified");
+ } else { /* is a skype name */
+ fprintf(p->phonebook_writing_fp,
+ "%s => ,%sSKY,,,hidefromdir=%s|phonebook_direct_calling_ext=%d%s%.4d|phonebook_entry_fromskype=%s|phonebook_entry_owner=%s\n",
+ where, where, "no",
+ p->skypiax_dir_entry_extension_prefix, "1",
+ skypiax_dir_entry_extension, "yes", "not_specified");
-#ifdef __CYGWIN__
- NOTICA("Sleping 5 secs, please wait...\n", SKYPIAX_P_LOG);
- sleep(5); /* without this pause, for some unknown (to me) reason it crashes on cygwin */
-#endif /* __CYGWIN__ */
- NOTICA("Unloaded Skypiax Module\n", SKYPIAX_P_LOG);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return 0;
-}
+ }
+ }
+ }
-/*!
- * \brief Return the count of active channels for this module
- *
- * \return the count of active channels for this module
- */
-int usecount()
-{
- int res;
- static struct skypiax_pvt *p = &skypiax_log_struct;
- if (option_debug > 10) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- }
-/* lock the skypiax_usecnt lock */
- LOKKA(&skypiax_usecnt_lock);
- /* retrieve the skypiax_usecnt */
- res = skypiax_usecnt;
-/* unlock the skypiax_usecnt lock */
- UNLOCKA(&skypiax_usecnt_lock);
- /* return the skypiax_usecnt */
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return res;
-}
+ skype_dir_file_written = 0;
-/*!
- * \brief Return the textual description of the module
- *
- * \return the textual description of the module
- */
-char *description()
-{
- static struct skypiax_pvt *p = &skypiax_log_struct;
- if (option_debug > 10) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- }
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return (char *) skypiax_desc;
-}
+ }
-/*!
- * \brief Return the ASTERISK_GPL_KEY
- *
- * \return the ASTERISK_GPL_KEY
- */
-char *key()
-{
- struct skypiax_pvt *p = NULL;
- if (option_debug > 10) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
+ }
+ p->skype_fullname[0] = '\0';
+
+ }
+ where = strsep(stringp, ", ");
+ }
+
+ p->skype_friends[0] = '\0';
+ }
+ }
+ } else {
+
+ ast_cli(fd,
+ "Skype not configured on the 'current' console, not importing from Skype client!\n");
+ }
+ //}
+ /*******************************************************************************************/
+ /*******************************************************************************************/
+ } else {
+ ast_cli(fd, "\n\nfailed to open the skypiax_dir.conf configuration file: %s\n", fn);
+ ERRORA("failed to open the skypiax_dir.conf configuration file: %s\n", SKYPIAX_P_LOG,
+ fn);
+ return RESULT_FAILURE;
}
- if (option_debug)
- NOTICA("Returning Key\n", SKYPIAX_P_LOG);
+ fclose(p->phonebook_writing_fp);
+ //skypiax_dir_create_extensions();
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return ASTERISK_GPL_KEY;
+ return RESULT_SUCCESS;
}
+#endif /* SKYPIAX_ADDITIONAL */
-/*!
- * \brief Create and initialize one interface for the module
- * \param cfg pointer to configuration data from skypiax.conf
- * \param ctg pointer to a category name to be found in cfg
- * \param is_first_category is this the first category in cfg
+#ifdef MOD_ALSA
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct at yahoo.com>
*
- * This function create and initialize one interface for the module
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II <anthmct at yahoo.com>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Anthony Minessale II <anthmct at yahoo.com>
+ *
+ *
+ * mod_alsa.c -- Alsa Endpoint Module
*
- * \return a pointer to the PVT structure of interface on success, NULL on error.
*/
-struct skypiax_pvt *skypiax_mkif(struct ast_config *cfg, char *ctg, int is_first_category)
+#include <switch.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include <alsa/asoundlib.h>
+
+#define MY_EVENT_RINGING "alsa::ringing"
+
+SWITCH_MODULE_LOAD_FUNCTION(mod_alsa_load);
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_alsa_shutdown);
+SWITCH_MODULE_DEFINITION(mod_alsa, mod_alsa_load, mod_alsa_shutdown, NULL);
+
+static switch_memory_pool_t *module_pool = NULL;
+//static int running = 1;
+
+#define SAMPLE_TYPE paInt16
+//#define SAMPLE_TYPE paFloat32
+typedef short SAMPLE;
+
+typedef switch_status_t (*pa_command_t) (char **argv, int argc, switch_stream_handle_t *stream);
+
+typedef enum {
+ GFLAG_NONE = 0,
+ GFLAG_EAR = (1 << 0),
+ GFLAG_MOUTH = (1 << 1),
+ GFLAG_RING = (1 << 2)
+} GFLAGS;
+
+typedef enum {
+ TFLAG_IO = (1 << 0),
+ TFLAG_INBOUND = (1 << 1),
+ TFLAG_OUTBOUND = (1 << 2),
+ TFLAG_DTMF = (1 << 3),
+ TFLAG_VOICE = (1 << 4),
+ TFLAG_HANGUP = (1 << 5),
+ TFLAG_LINEAR = (1 << 6),
+ TFLAG_ANSWER = (1 << 7),
+ TFLAG_HUP = (1 << 8),
+ TFLAG_MASTER = (1 << 9)
+} TFLAGS;
+
+struct private_object {
+ unsigned int flags;
+ switch_core_session_t *session;
+ switch_caller_profile_t *caller_profile;
+ char call_id[50];
+ int sample_rate;
+ int codec_ms;
+ switch_mutex_t *flag_mutex;
+ char *hold_file;
+ switch_file_handle_t fh;
+ switch_file_handle_t *hfh;
+ switch_frame_t hold_frame;
+ unsigned char holdbuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
+ switch_codec_t write_codec;
+ switch_timer_t timer;
+ struct private_object *next;
+};
+
+typedef struct private_object private_t;
+
+static struct {
+ int debug;
+ int port;
+ char *cid_name;
+ char *cid_num;
+ char *dialplan;
+ char *ring_file;
+ char *hold_file;
+ char *timer_name;
+ char *device_name;
+ int call_id;
+ switch_hash_t *call_hash;
+ switch_mutex_t *device_lock;
+ switch_mutex_t *pvt_lock;
+ switch_mutex_t *flag_mutex;
+ int sample_rate;
+ int codec_ms;
+ snd_pcm_t *audio_stream_in;
+ snd_pcm_t *audio_stream_out;
+
+
+ switch_codec_t read_codec;
+ switch_codec_t write_codec;
+ switch_frame_t read_frame;
+ switch_frame_t cng_frame;
+ unsigned char databuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
+ unsigned char cngbuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
+ private_t *call_list;
+ int ring_interval;
+ GFLAGS flags;
+ switch_timer_t timer;
+} globals;
+
+
+#define PA_MASTER 1
+#define PA_SLAVE 0
+
+
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_cid_name, globals.cid_name);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_cid_num, globals.cid_num);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_ring_file, globals.ring_file);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_hold_file, globals.hold_file);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_timer_name, globals.timer_name);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_device_name, globals.device_name);
+
+#define is_master(t) switch_test_flag(t, TFLAG_MASTER)
+static void add_pvt(private_t *tech_pvt, int master);
+static void remove_pvt(private_t *tech_pvt);
+static switch_status_t channel_on_init(switch_core_session_t *session);
+static switch_status_t channel_on_hangup(switch_core_session_t *session);
+static switch_status_t channel_on_routing(switch_core_session_t *session);
+static switch_status_t channel_on_exchange_media(switch_core_session_t *session);
+static switch_status_t channel_on_soft_execute(switch_core_session_t *session);
+static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event,
+ switch_caller_profile_t *outbound_profile,
+ switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags);
+static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id);
+static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
+static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig);
+static switch_status_t engage_device(unsigned int samplerate, int codec_ms);
+static switch_status_t load_config(void);
+SWITCH_STANDARD_API(pa_cmd);
+
+
+
+/*
+ State methods they get called when the state changes to the specific state
+ returning SWITCH_STATUS_SUCCESS tells the core to execute the standard state method next
+ so if you fully implement the state you can return SWITCH_STATUS_FALSE to skip it.
+*/
+static switch_status_t channel_on_init(switch_core_session_t *session)
{
- struct skypiax_pvt *tmp;
- struct ast_variable *v;
- int res;
+ switch_channel_t *channel;
+ private_t *tech_pvt = NULL;
+ switch_time_t last;
+ int waitsec = globals.ring_interval * 1000000;
+ switch_file_handle_t fh = { 0 };
+ const char *val, *ring_file = NULL, *hold_file = NULL;
+ int16_t abuf[2048];
- int debug_all = 0;
- int debug_at = 0;
- int debug_fbus2 = 0;
- int debug_serial = 0;
- int debug_sound = 0;
- int debug_pbx = 0;
- int debug_skype = 0;
- int debug_call = 0;
- int debug_locks = 0;
- int debug_monitorlocks = 0;
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
- ast_log(LOG_DEBUG, "ENTERING FUNC\n");
- /* alloc memory for PVT */
- tmp = malloc(sizeof(struct skypiax_pvt));
- if (tmp == NULL) { /* fail */
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_TMP_LOG);
- ast_log(LOG_DEBUG, "EXITING FUNC\n");
- }
- return NULL;
- }
- /* clear memory for PVT */
- memset(tmp, 0, sizeof(struct skypiax_pvt));
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
- /* if we are reading the "first" category of the config file, take SELECTED values as defaults, overriding the values in skypiax_default */
- if (is_first_category == 1) {
- /* for each variable in category, copy it in the skypiax_default struct */
- for (v = ast_variable_browse(cfg, ctg); v; v = v->next) {
- M_START(v->name, v->value);
- M_STR("context", skypiax_default.context)
- M_STR("language", skypiax_default.language)
- M_STR("extension", skypiax_default.exten)
- M_F("playback_boost",
- skypiax_store_boost(v->value, &skypiax_default.playback_boost))
- M_F("capture_boost",
- skypiax_store_boost(v->value, &skypiax_default.capture_boost))
- M_UINT("skypiax_dir_entry_extension_prefix",
- skypiax_default.skypiax_dir_entry_extension_prefix)
- M_END(;);
- }
- }
+ last = switch_timestamp_now() - waitsec;
- /* initialize the newly created PVT from the skypiax_default values */
- *tmp = skypiax_default;
- /* the category name becomes the interface name */
- tmp->name = strdup(ctg);
- /* for each category in config file, "first" included, read in ALL the values */
- for (v = ast_variable_browse(cfg, ctg); v; v = v->next) {
- M_START(v->name, v->value);
+ if ((val = switch_channel_get_variable(channel, "pa_hold_file"))) {
+ hold_file = val;
+ } else {
+ hold_file = globals.hold_file;
+ }
- M_BOOL("debug_all", debug_all)
- M_BOOL("debug_at", debug_at)
- M_BOOL("debug_fbus2", debug_fbus2)
- M_BOOL("debug_serial", debug_serial)
- M_BOOL("debug_sound", debug_sound)
- M_BOOL("debug_pbx", debug_pbx)
- M_BOOL("debug_skype", debug_skype)
- M_BOOL("debug_call", debug_call)
- M_BOOL("debug_locks", debug_locks)
- M_BOOL("debug_monitorlocks", debug_monitorlocks)
- M_BOOL("skype", tmp->skype)
- M_STR("context", tmp->context)
- M_STR("language", tmp->language)
- M_STR("extension", tmp->exten)
- M_F("playback_boost", skypiax_store_boost(v->value, &tmp->playback_boost))
- M_F("capture_boost", skypiax_store_boost(v->value, &tmp->capture_boost))
- M_UINT("skypiax_dir_entry_extension_prefix",
- tmp->skypiax_dir_entry_extension_prefix)
- M_END(;);
- }
+ if (hold_file) {
+ tech_pvt->hold_file = switch_core_session_strdup(session, hold_file);
+ }
- if (debug_all) {
- skypiax_debug = skypiax_debug | DEBUG_ALL;
- if (!option_debug) {
- WARNINGA
- ("DEBUG_ALL activated, but option_debug is 0. You have to set debug level higher than zero to see some debugging output. Please use the command \"set debug 10\" or start Asterisk with \"-dddddddddd\" option for full DEBUG_ALL debugging output.\n",
- SKYPIAX_TMP_LOG);
- } else {
- NOTICA("DEBUG_ALL activated. \n", SKYPIAX_TMP_LOG);
- }
- }
+ if (switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
- if (debug_fbus2) {
- skypiax_debug = skypiax_debug | DEBUG_FBUS2;
- if (!option_debug) {
- WARNINGA
- ("DEBUG_FBUS2 activated, but option_debug is 0. You have to set debug level higher than zero to see some debugging output. Please use the command \"set debug 10\" or start Asterisk with \"-dddddddddd\" option for full DEBUG_FBUS2 debugging output.\n",
- SKYPIAX_TMP_LOG);
- } else {
- NOTICA("DEBUG_FBUS2 activated. \n", SKYPIAX_TMP_LOG);
- }
- }
- if (debug_serial) {
- skypiax_debug = skypiax_debug | DEBUG_SERIAL;
- if (!option_debug) {
- WARNINGA
- ("DEBUG_SERIAL activated, but option_debug is 0. You have to set debug level higher than zero to see some debugging output. Please use the command \"set debug 10\" or start Asterisk with \"-dddddddddd\" option for full DEBUG_SERIAL debugging output.\n",
- SKYPIAX_TMP_LOG);
- } else {
- NOTICA("DEBUG_SERIAL activated. \n", SKYPIAX_TMP_LOG);
- }
- }
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL INIT %d %d\n",
+ switch_channel_get_name(channel), switch_channel_get_state(channel), switch_test_flag(tech_pvt, TFLAG_ANSWER));
- if (debug_sound) {
- skypiax_debug = skypiax_debug | DEBUG_SOUND;
- if (!option_debug) {
- WARNINGA
- ("DEBUG_SOUND activated, but option_debug is 0. You have to set debug level higher than zero to see some debugging output. Please use the command \"set debug 10\" or start Asterisk with \"-dddddddddd\" option for full DEBUG_SOUND debugging output.\n",
- SKYPIAX_TMP_LOG);
- } else {
- NOTICA("DEBUG_SOUND activated. \n", SKYPIAX_TMP_LOG);
- }
- }
- if (debug_pbx) {
- skypiax_debug = skypiax_debug | DEBUG_PBX;
- if (!option_debug) {
- WARNINGA
- ("DEBUG_PBX activated, but option_debug is 0. You have to set debug level higher than zero to see some debugging output. Please use the command \"set debug 10\" or start Asterisk with \"-dddddddddd\" option for full DEBUG_PBX debugging output.\n",
- SKYPIAX_TMP_LOG);
- } else {
- NOTICA("DEBUG_PBX activated. \n", SKYPIAX_TMP_LOG);
- }
- }
- if (debug_skype) {
- skypiax_debug = skypiax_debug | DEBUG_SKYPE;
- if (!option_debug) {
- WARNINGA
- ("DEBUG_SKYPE activated, but option_debug is 0. You have to set debug level higher than zero to see some debugging output. Please use the command \"set debug 10\" or start Asterisk with \"-dddddddddd\" option for full DEBUG_SKYPE debugging output.\n",
- SKYPIAX_TMP_LOG);
- } else {
- NOTICA("DEBUG_SKYPE activated. \n", SKYPIAX_TMP_LOG);
- }
- }
+ if (engage_device(tech_pvt->sample_rate, tech_pvt->codec_ms) != SWITCH_STATUS_SUCCESS) {
+ switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
+ add_pvt(tech_pvt, PA_SLAVE);
+
+ ring_file = globals.ring_file;
+ if ((val = switch_channel_get_variable(channel, "pa_ring_file"))) {
+ ring_file = val;
+ }
+
+ if (switch_test_flag((&globals), GFLAG_RING)) {
+ ring_file = NULL;
+ }
+ switch_set_flag_locked((&globals), GFLAG_RING);
+ if (ring_file) {
+ if (switch_core_file_open(&fh,
+ ring_file,
+ globals.read_codec.implementation->number_of_channels,
+ globals.read_codec.implementation->actual_samples_per_second,
+ SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) == SWITCH_STATUS_SUCCESS) {
+
+ if (engage_device(fh.samplerate, fh.channels) != SWITCH_STATUS_SUCCESS) {
+ switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Ring Error!\n");
+ switch_core_file_close(&fh);
+ return SWITCH_STATUS_GENERR;
+ }
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot open %s, disabling ring file!\n", ring_file);
+ ring_file = NULL;
+ }
+ }
+ }
+
+ switch_core_session_queue_indication(session, SWITCH_MESSAGE_INDICATE_RINGING);
+ switch_channel_mark_ring_ready(channel);
+
+ while (switch_channel_get_state(channel) == CS_INIT && !switch_test_flag(tech_pvt, TFLAG_ANSWER)) {
+ if (switch_timestamp_now() - last >= waitsec) {
+ char buf[512];
+ switch_event_t *event;
+
+ snprintf(buf, sizeof(buf), "BRRRRING! BRRRRING! call %s\n", tech_pvt->call_id);
+
+ if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_RINGING) == SWITCH_STATUS_SUCCESS) {
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_info", "%s", buf);
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "call_id", "%s", tech_pvt->call_id);
+ switch_channel_event_set_data(channel, event);
+ switch_event_fire(&event);
+ }
- if (debug_call) {
- skypiax_debug = skypiax_debug | DEBUG_CALL;
- if (!option_debug) {
- WARNINGA
- ("DEBUG_CALL activated, but option_debug is 0. You have to set debug level higher than zero to see some debugging output. Please use the command \"set debug 10\" or start Asterisk with \"-dddddddddd\" option for full DEBUG_CALL debugging output.\n",
- SKYPIAX_TMP_LOG);
- } else {
- NOTICA("DEBUG_CALL activated. \n", SKYPIAX_TMP_LOG);
- }
- }
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s\n", buf);
+ last = switch_timestamp_now();
+ if (ring_file) {
+ unsigned int pos = 0;
+ switch_core_file_seek(&fh, &pos, 0, SEEK_SET);
+ for (;;) {
+ switch_size_t olen = 1024;
+ switch_core_file_read(&fh, abuf, &olen);
+ if (olen == 0) {
+ break;
+ }
+ snd_pcm_writei(globals.audio_stream_out, abuf, (int) olen);
+ }
+ }
+ }
- if (debug_locks) {
- skypiax_debug = skypiax_debug | DEBUG_LOCKS;
- if (!option_debug) {
- WARNINGA
- ("DEBUG_LOCKS activated, but option_debug is 0. You have to set debug level higher than zero to see some debugging output. Please use the command \"set debug 10\" or start Asterisk with \"-dddddddddd\" option for full DEBUG_LOCKS debugging output.\n",
- SKYPIAX_TMP_LOG);
- } else {
- NOTICA("DEBUG_LOCKS activated. \n", SKYPIAX_TMP_LOG);
- }
- }
+ switch_yield(globals.read_codec.implementation->microseconds_per_packet);
- if (debug_monitorlocks) {
- skypiax_debug = skypiax_debug | DEBUG_MONITORLOCKS;
- if (!option_debug) {
- WARNINGA
- ("DEBUG_MONITORLOCKS activated, but option_debug is 0. You have to set debug level higher than zero to see some debugging output. Please use the command \"set debug 10\" or start Asterisk with \"-dddddddddd\" option for full DEBUG_MONITORLOCKS debugging output.\n",
- SKYPIAX_TMP_LOG);
- } else {
- NOTICA("DEBUG_MONITORLOCKS activated. \n", SKYPIAX_TMP_LOG);
- }
- }
+ }
+ switch_clear_flag_locked((&globals), GFLAG_RING);
+ }
- if (option_debug > 1) {
- DEBUGA_SOUND("playback_boost is %f\n", SKYPIAX_TMP_LOG, tmp->playback_boost);
- DEBUGA_SOUND("capture_boost is %f\n", SKYPIAX_TMP_LOG, tmp->capture_boost);
- }
- /* if skype is true for this interface, let's check if another interface has skype true */
- if (tmp->skype) {
- struct skypiax_pvt *p = NULL, *p2 = NULL;
- /* lock the skypiax_iflock, maybe unneeded */
- LOKKA(&skypiax_iflock);
- p = skypiax_iflist;
- /* for each pvt in the interfaces list (skypiax_iflist) */
- while (p) {
- p2 = p->next;
- /* if another interface has skype true */
- if (p->skype) {
- ERRORA
- ("This interface (category '[%s]') has 'skype=yes' in config, but up in skypiax.conf config file the interface category '[%s]' has yet 'skype=yes'. Only one interface at time can support skype. I'm sure, I wrote it ;). Setting 'skype=no' for interface category '[%s] and continuing\n",
- SKYPIAX_P_LOG, tmp->name, p->name, tmp->name);
- /* set this interface's skype to false */
- tmp->skype = 0;
- }
- /* next interface, please */
- p = p2;
- }
- /* unlock the skypiax_iflock */
- UNLOCKA(&skypiax_iflock);
- }
-/* initialize the soundcard channels (input and output) used by this interface (a multichannel soundcard can be used by multiple interfaces), optionally starting the sound managing threads */
- res = skypiax_sound_init(tmp);
- if (res == -1) {
- ERRORA("Failed initializing sound device\n", SKYPIAX_TMP_LOG);
- /* we failed, free the PVT */
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_TMP_LOG);
- }
- free(tmp);
- return NULL;
- }
- res = pipe(tmp->AsteriskHandlesAst.fdesc);
- if (res) {
- ast_log(LOG_ERROR, "Unable to create skype pipe\n");
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_TMP_LOG);
- }
- free(tmp);
- return NULL;
- }
- fcntl(tmp->AsteriskHandlesAst.fdesc[0], F_SETFL, O_NONBLOCK);
- fcntl(tmp->AsteriskHandlesAst.fdesc[1], F_SETFL, O_NONBLOCK);
- tmp->skype_thread = AST_PTHREADT_NULL;
- if (tmp->skype) {
- if (option_debug > 1)
- ast_log(LOG_DEBUG, "TO BE started skype_thread=%lu STOP=%lu NULL=%lu\n",
- (unsigned long) tmp->skype_thread, (unsigned long) AST_PTHREADT_STOP,
- (unsigned long) AST_PTHREADT_NULL);
-#ifdef __CYGWIN__
- if (ast_pthread_create
- (&tmp->skype_thread, NULL, do_skype_thread, &tmp->AsteriskHandlesAst) < 0) {
- ast_log(LOG_ERROR, "Unable to start skype_main thread.\n");
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_TMP_LOG);
- }
- free(tmp);
- return NULL;
- }
-#else /* __CYGWIN__ */
-#ifdef WANT_SKYPE_X11
- if (option_debug > 1)
- ast_log(LOG_DEBUG, "AsteriskHandlesfd: %d\n", tmp->AsteriskHandlesAst.fdesc[1]);
- if (ast_pthread_create(&tmp->skype_thread, NULL, do_skype_thread, tmp) < 0) {
- ast_log(LOG_ERROR, "Unable to start skype_main thread.\n");
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_TMP_LOG);
- }
- free(tmp);
- return NULL;
- }
-#endif /* WANT_SKYPE_X11 */
-#endif /* __CYGWIN__ */
- usleep(100000); //0.1 sec
- if( tmp->skype_thread == AST_PTHREADT_NULL){
- ast_log(LOG_ERROR, "Unable to start skype_main thread.\n");
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_TMP_LOG);
- }
- free(tmp);
- return NULL;
- }
- if (option_debug > 1)
- ast_log(LOG_DEBUG, "STARTED skype_thread=%lu STOP=%lu NULL=%lu\n",
- (unsigned long) tmp->skype_thread, (unsigned long) AST_PTHREADT_STOP,
- (unsigned long) AST_PTHREADT_NULL);
- }
+ if (ring_file) {
+ switch_core_file_close(&fh);
+ switch_core_codec_destroy(&tech_pvt->write_codec);
+ switch_core_timer_destroy(&tech_pvt->timer);
+ }
+
+ if (switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
+ if (!switch_test_flag(tech_pvt, TFLAG_ANSWER)) {
+ switch_channel_hangup(channel, SWITCH_CAUSE_NO_ANSWER);
+ return SWITCH_STATUS_SUCCESS;
+ }
+ }
+
+ switch_set_flag_locked(tech_pvt, TFLAG_IO);
+
+ /* Move channel's state machine to ROUTING */
+ switch_channel_set_state(channel, CS_ROUTING);
+
+ return SWITCH_STATUS_SUCCESS;
- /* return the newly created skypiax_pvt */
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_TMP_LOG);
- }
- return tmp;
}
-/*! \brief (Re)Start the module main monitor thread, watching for incoming calls on the interfaces */
-int skypiax_restart_monitor(void)
+static switch_status_t channel_on_routing(switch_core_session_t *session)
{
- static struct skypiax_pvt *p = &skypiax_log_struct;
+ switch_channel_t *channel = NULL;
+ private_t *tech_pvt = NULL;
- if (option_debug > 10) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- }
- /* If we're supposed to be stopped -- stay stopped */
- if (skypiax_monitor_thread == AST_PTHREADT_STOP) {
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return 0;
- }
- LOKKA(&skypiax_monlock);
- /* Do not seems possible to me that this function can be called by the very same monitor thread, but let's be paranoid */
- if (skypiax_monitor_thread == pthread_self()) {
- UNLOCKA(&skypiax_monlock);
- ERRORA("Cannot kill myself\n", SKYPIAX_P_LOG);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return -1;
- }
- /* if the monitor thread exists */
- if (skypiax_monitor_thread != AST_PTHREADT_NULL) {
- /* Wake up the thread, it can be stuck waiting in a select or so */
- pthread_kill(skypiax_monitor_thread, SIGURG);
- } else {
- /* the monitor thread does not exists, start a new monitor */
- if (ast_pthread_create(&skypiax_monitor_thread, NULL, skypiax_do_monitor, NULL) < 0) {
- UNLOCKA(&skypiax_monlock);
- ERRORA("Unable to start monitor thread.\n", SKYPIAX_P_LOG);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return -1;
- }
- }
- UNLOCKA(&skypiax_monlock);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return 0;
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL ROUTING\n", switch_channel_get_name(channel));
+
+ return SWITCH_STATUS_SUCCESS;
}
-/*! \brief The skypiax monitoring thread
- * \note This thread monitors all the skypiax interfaces that are not in a call
- * (and thus do not have a separate thread) indefinitely
- * */
-void *skypiax_do_monitor(void *data)
+static switch_status_t channel_on_execute(switch_core_session_t *session)
{
- fd_set rfds;
- int res;
- struct skypiax_pvt *p = NULL;
- int max = -1;
- struct timeval to;
- time_t now_timestamp;
- if (option_debug > 10) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- }
- if (pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL)) {
- ERRORA("Unable to set cancel type to deferred\n", SKYPIAX_P_LOG);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return NULL;
- }
+ switch_channel_t *channel = NULL;
+ private_t *tech_pvt = NULL;
- for (;;) {
- pthread_testcancel();
- /* Don't let anybody kill us right away. Nobody should lock the interface list
- and wait for the monitor list, but the other way around is okay. */
- PUSHA_UNLOCKA(&skypiax_monlock);
- MONITORLOKKA(&skypiax_monlock);
- /* Lock the interface list */
- PUSHA_UNLOCKA(&skypiax_iflock);
- MONITORLOKKA(&skypiax_iflock);
- /* Build the stuff we're going to select on, that is the skypiax_serial_fd of every
- skypiax_pvt that does not have an associated owner channel. In the case of FBUS2 3310
- and in the case of PROTOCOL_NO_SERIAL we add the audio_fd as well, because there is not serial signaling of incoming calls */
- FD_ZERO(&rfds);
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
- time(&now_timestamp);
- p = skypiax_iflist;
- while (p) {
- if (!p->owner) {
- /* This interface needs to be watched, as it lacks an owner */
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL EXECUTE\n", switch_channel_get_name(channel));
+
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static void deactivate_audio_device(void)
+{
+
+ switch_mutex_lock(globals.device_lock);
+ if (globals.audio_stream_in) {
+ snd_pcm_drain(globals.audio_stream_in);
+ snd_pcm_close(globals.audio_stream_in);
+ globals.audio_stream_in = NULL;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Close IN stream\n");
+ }
+ if (globals.audio_stream_out) {
+ snd_pcm_drain(globals.audio_stream_out);
+ snd_pcm_close(globals.audio_stream_out);
+ globals.audio_stream_out = NULL;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Close OUT stream\n");
+ }
+ switch_mutex_unlock(globals.device_lock);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "DONE\n");
+}
- if (p->skype) {
- if (FD_ISSET(p->AsteriskHandlesAst.fdesc[0], &rfds))
- ERRORA("Descriptor %d (AsteriskHandlesAst.fdesc[0]) appears twice ?\n",
- SKYPIAX_P_LOG, p->AsteriskHandlesAst.fdesc[0]);
- if (p->AsteriskHandlesAst.fdesc[0] > 0) {
- FD_SET(p->AsteriskHandlesAst.fdesc[0], &rfds);
- if (p->AsteriskHandlesAst.fdesc[0] > max)
- max = p->AsteriskHandlesAst.fdesc[0];
- }
- }
+static void add_pvt(private_t *tech_pvt, int master)
+{
+ private_t *tp;
+ uint8_t in_list = 0;
- }
- /* next interface, please */
- p = p->next;
- }
- /* Okay, now that we know what to do, release the interface lock */
- MONITORUNLOCKA(&skypiax_iflock);
- POPPA_UNLOCKA(&skypiax_iflock);
- /* And from now on, we're okay to be killed, so release the monitor lock as well */
- MONITORUNLOCKA(&skypiax_monlock);
- POPPA_UNLOCKA(&skypiax_monlock);
+ switch_mutex_lock(globals.pvt_lock);
- /* you want me to die? */
- pthread_testcancel();
+ if (switch_strlen_zero(tech_pvt->call_id)) {
+ snprintf(tech_pvt->call_id, sizeof(tech_pvt->call_id), "%d", ++globals.call_id);
+ switch_core_hash_insert(globals.call_hash, tech_pvt->call_id, tech_pvt);
+ switch_core_session_set_read_codec(tech_pvt->session, &globals.read_codec);
+ switch_core_session_set_write_codec(tech_pvt->session, &globals.write_codec);
+ }
- /* Wait for something to happen */
- to.tv_sec = 0;
- to.tv_usec = 500000; /* we select with this timeout because under cygwin we avoid the signal usage, so there is no way to end the thread if it is stuck waiting for select */
- res = ast_select(max + 1, &rfds, NULL, NULL, &to);
+ for (tp = globals.call_list; tp; tp = tp->next) {
+ if (tp == tech_pvt) {
+ in_list = 1;
+ }
+ if (master) {
+ switch_clear_flag_locked(tp, TFLAG_MASTER);
+ }
+ }
- /* you want me to die? */
- pthread_testcancel();
- /* Okay, select has finished. Let's see what happened. */
+ if (master) {
+ if (!in_list) {
+ tech_pvt->next = globals.call_list;
+ globals.call_list = tech_pvt;
+ }
+ switch_set_flag_locked(tech_pvt, TFLAG_MASTER);
- /* If there are errors... */
- if (res < 0) {
- if (errno == EINTR) /* EINTR is just the select
- being interrupted by a SIGURG, or so */
- continue;
- else {
- ERRORA("select returned %d: %s\n", SKYPIAX_P_LOG, res, strerror(errno));
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return NULL;
- }
- }
+ } else if (!in_list) {
+ for (tp = globals.call_list; tp && tp->next; tp = tp->next);
+ if (tp) {
+ tp->next = tech_pvt;
+ } else {
+ globals.call_list = tech_pvt;
+ }
+ }
- /* must not be killed while skypiax_iflist is locked */
- PUSHA_UNLOCKA(&skypiax_monlock);
- MONITORLOKKA(&skypiax_monlock);
- /* Alright, lock the interface list again, and let's look and see what has
- happened */
- PUSHA_UNLOCKA(&skypiax_iflock);
- MONITORLOKKA(&skypiax_iflock);
+ switch_mutex_unlock(globals.pvt_lock);
+}
- p = skypiax_iflist;
- for (; p; p = p->next) {
+static void remove_pvt(private_t *tech_pvt)
+{
+ private_t *tp, *last = NULL;
- if (p->skype) {
- if (FD_ISSET(p->AsteriskHandlesAst.fdesc[0], &rfds)) {
- res = skypiax_skype_read(p);
- if (res == CALLFLOW_INCOMING_CALLID || res == CALLFLOW_INCOMING_RING) {
- //ast_log(LOG_NOTICE, "CALLFLOW_INCOMING_RING SKYPE\n");
- DEBUGA_SKYPE("CALLFLOW_INCOMING_RING\n", SKYPIAX_P_LOG);
- skypiax_new(p, AST_STATE_RING, p->context /* p->context */ );
- }
- }
- }
+ switch_mutex_lock(globals.pvt_lock);
+ for (tp = globals.call_list; tp; tp = tp->next) {
+ switch_clear_flag_locked(tp, TFLAG_MASTER);
+ if (tp == tech_pvt) {
+ if (last) {
+ last->next = tp->next;
+ } else {
+ globals.call_list = tp->next;
+ }
+ }
+ last = tp;
+ }
- }
- MONITORUNLOCKA(&skypiax_iflock);
- POPPA_UNLOCKA(&skypiax_iflock);
- MONITORUNLOCKA(&skypiax_monlock);
- POPPA_UNLOCKA(&skypiax_monlock);
- pthread_testcancel();
- }
-/* Never reached */
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return NULL;
+ if (globals.call_list) {
+ switch_set_flag_locked(globals.call_list, TFLAG_MASTER);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "No more channels\n");
+ }
+ switch_mutex_unlock(globals.pvt_lock);
}
-/*!
- * \brief Initialize the soundcard channels (input and output) used by one interface (a multichannel soundcard can be used by multiple interfaces)
- * \param p the skypiax_pvt of the interface
- *
- * This function initialize the soundcard channels (input and output) used by one interface (a multichannel soundcard can be used by multiple interfaces). It simply pass its parameters to the right function for the sound system for which has been compiled, eg. alsa_init for ALSA, oss_init for OSS, winmm_init for Windows Multimedia, etc and return the result
- *
- * \return zero on success, -1 on error.
- */
-
-int skypiax_sound_init(struct skypiax_pvt *p)
+static switch_status_t channel_on_hangup(switch_core_session_t *session)
{
- if (option_debug > 10) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- }
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return skypiax_skypeaudio_init(p);
-}
+ switch_channel_t *channel = NULL;
+ private_t *tech_pvt = NULL;
-/*!
- * \brief Shutdown the soundcard channels (input and output) used by one interface (a multichannel soundcard can be used by multiple interfaces)
- * \param p the skypiax_pvt of the interface
- *
- * This function shutdown the soundcard channels (input and output) used by one interface (a multichannel soundcard can be used by multiple interfaces). It simply pass its parameters to the right function for the sound system for which has been compiled, eg. alsa_shutdown for ALSA, oss_shutdown for OSS, winmm_shutdown for Windows Multimedia, etc and return the result
- *
- * \return zero on success, -1 on error.
- */
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
-int skypiax_sound_shutdown(struct skypiax_pvt *p)
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ remove_pvt(tech_pvt);
+
+ switch_clear_flag_locked(tech_pvt, TFLAG_IO);
+ switch_set_flag_locked(tech_pvt, TFLAG_HUP);
+
+ switch_core_hash_delete(globals.call_hash, tech_pvt->call_id);
+
+ if (tech_pvt->hfh) {
+ tech_pvt->hfh = NULL;
+ switch_core_file_close(&tech_pvt->fh);
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL HANGUP\n", switch_channel_get_name(channel));
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig)
{
+ switch_channel_t *channel = NULL;
+ private_t *tech_pvt = NULL;
- if (option_debug > 10) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- }
- //return skypiax_portaudio_shutdown(p);
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return -1;
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ switch (sig) {
+ case SWITCH_SIG_KILL:
+ switch_set_flag_locked(tech_pvt, TFLAG_HUP);
+ switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
+ break;
+ default:
+ break;
+ }
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL KILL\n", switch_channel_get_name(channel));
+
+
+ return SWITCH_STATUS_SUCCESS;
}
-/*! \brief Read audio frames from interface */
-struct ast_frame *skypiax_sound_read(struct skypiax_pvt *p)
+static switch_status_t channel_on_soft_execute(switch_core_session_t *session)
{
- struct ast_frame *f = NULL;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CHANNEL TRANSMIT\n");
+ return SWITCH_STATUS_SUCCESS;
+}
- if (option_debug > 100) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- }
- f = skypiax_skypeaudio_read(p);
- if (option_debug > 100) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return f;
+static switch_status_t channel_on_exchange_media(switch_core_session_t *session)
+{
+ switch_channel_t *channel = NULL;
+ private_t *tech_pvt = NULL;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CHANNEL LOOPBACK\n");
+
+ return SWITCH_STATUS_SUCCESS;
}
-/*! \brief Send audio frame to interface */
-int skypiax_sound_write(struct skypiax_pvt *p, struct ast_frame *f)
+
+static switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)
{
- int ret = -1;
+ private_t *tech_pvt = NULL;
- if (option_debug > 100) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- }
- ret = skypiax_skypeaudio_write(p, f);
- if (option_debug > 100) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return ret;
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "DTMF ON CALL %s [%c]\n", tech_pvt->call_id, dtmf->digit);
+
+ return SWITCH_STATUS_SUCCESS;
}
-/*!
- * \brief This thread runs during a call, and monitor the interface serial port for signaling, like hangup, caller id, etc
- *
- */
-void *skypiax_do_controldev_thread(void *data)
+static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
{
- struct skypiax_pvt *p = data;
- int res;
+ switch_channel_t *channel = NULL;
+ private_t *tech_pvt = NULL;
+ int samples = 0;
+ switch_status_t status = SWITCH_STATUS_FALSE;
- if (option_debug > 10) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- }
- DEBUGA_SERIAL("In skypiax_do_controldev_thread: started, p=%p\n", SKYPIAX_P_LOG, p);
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ if (!globals.audio_stream_in) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (switch_test_flag(tech_pvt, TFLAG_HUP)) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (!switch_test_flag(tech_pvt, TFLAG_IO)) {
+ goto cng;
+ }
+
+ if (!is_master(tech_pvt)) {
+ if (tech_pvt->hold_file) {
+ if (!tech_pvt->hfh) {
+ int codec_ms = tech_pvt->codec_ms ? tech_pvt->codec_ms : globals.codec_ms;
+ int sample_rate = tech_pvt->sample_rate ? tech_pvt->sample_rate : globals.sample_rate;
+
+ if (switch_core_codec_init(&tech_pvt->write_codec,
+ "L16",
+ NULL,
+ sample_rate,
+ codec_ms,
+ 1,
+ SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
+ NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n");
+ switch_core_codec_destroy(&globals.read_codec);
+ tech_pvt->hold_file = NULL;
+ goto cng;
+ }
+
+ if (switch_core_file_open(&tech_pvt->fh,
+ tech_pvt->hold_file,
+ globals.read_codec.implementation->number_of_channels,
+ globals.read_codec.implementation->actual_samples_per_second,
+ SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
+ switch_core_codec_destroy(&tech_pvt->write_codec);
+ tech_pvt->hold_file = NULL;
+ goto cng;
+ }
+
+ tech_pvt->hfh = &tech_pvt->fh;
+ tech_pvt->hold_frame.data = tech_pvt->holdbuf;
+ tech_pvt->hold_frame.buflen = sizeof(tech_pvt->holdbuf);
+ tech_pvt->hold_frame.rate = sample_rate;
+ tech_pvt->hold_frame.codec = &tech_pvt->write_codec;
+ }
+
+ goto hold;
+ }
+ cng:
+ switch_yield(globals.read_codec.implementation->microseconds_per_packet);
+ *frame = &globals.cng_frame;
+ return SWITCH_STATUS_SUCCESS;
+
+ hold:
+
+ {
+ switch_size_t olen = globals.read_codec.implementation->samples_per_packet;
+ if (switch_core_timer_next(&tech_pvt->timer) != SWITCH_STATUS_SUCCESS) {
+ switch_core_file_close(&tech_pvt->fh);
+ switch_core_codec_destroy(&tech_pvt->write_codec);
+ goto cng;
+ }
+ switch_core_file_read(tech_pvt->hfh, tech_pvt->hold_frame.data, &olen);
+
+ if (olen == 0) {
+ unsigned int pos = 0;
+ switch_core_file_seek(tech_pvt->hfh, &pos, 0, SEEK_SET);
+ goto cng;
+ }
+
+
+ tech_pvt->hold_frame.datalen = (uint32_t) (olen * sizeof(int16_t));
+ tech_pvt->hold_frame.samples = (uint32_t) olen;
+ tech_pvt->hold_frame.timestamp = tech_pvt->timer.samplecount;
+ *frame = &tech_pvt->hold_frame;
+
+ }
- if (pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL)) {
- ERRORA("Unable to set cancel type to deferred\n", SKYPIAX_P_LOG);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return NULL;
- }
+ return SWITCH_STATUS_SUCCESS;
+ }
- while (1) {
- usleep(1000);
- pthread_testcancel();
- if (p->skype) {
- res = skypiax_skype_read(p);
- if (res == CALLFLOW_INCOMING_HANGUP) {
- if (option_debug)
- DEBUGA_SKYPE("skype call ended\n", SKYPIAX_P_LOG);
- if (p->owner) {
- pthread_testcancel();
- ast_queue_control(p->owner, AST_CONTROL_HANGUP);
- }
- }
- }
- }
+ switch_mutex_lock(globals.device_lock);
+ if ((samples = snd_pcm_readi(globals.audio_stream_in, globals.read_frame.data, globals.read_codec.implementation->samples_per_packet)) > 0) {
+ globals.read_frame.datalen = samples * 2;
+ globals.read_frame.samples = samples;
+
+ switch_core_timer_check(&globals.timer, SWITCH_TRUE);
+ globals.read_frame.timestamp = globals.timer.samplecount;
+ *frame = &globals.read_frame;
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return NULL;
+ if (!switch_test_flag((&globals), GFLAG_MOUTH)) {
+ memset(globals.read_frame.data, 255, globals.read_frame.datalen);
+ }
-}
+ status = SWITCH_STATUS_SUCCESS;
+ }
+ switch_mutex_unlock(globals.device_lock);
-/************************************************/
+ return status;
+}
-/* LUIGI RIZZO's magic */
-/*
- * store the boost factor
- */
-#ifdef ASTERISK_VERSION_1_6
-void skypiax_store_boost(const char *s, double *boost)
-#else
-void skypiax_store_boost(char *s, double *boost)
-#endif /* ASTERISK_VERSION_1_6 */
+static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
{
- struct skypiax_pvt *p = NULL;
+ switch_channel_t *channel = NULL;
+ private_t *tech_pvt = NULL;
+ switch_status_t status = SWITCH_STATUS_FALSE;
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ if (!globals.audio_stream_out) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (switch_test_flag(tech_pvt, TFLAG_HUP)) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (!is_master(tech_pvt) || !switch_test_flag(tech_pvt, TFLAG_IO)) {
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ if (globals.audio_stream_out) {
+ if (switch_test_flag((&globals), GFLAG_EAR)) {
+ snd_pcm_writei(globals.audio_stream_out, (short *) frame->data, (int) (frame->datalen / sizeof(SAMPLE)));
+ }
+ status = SWITCH_STATUS_SUCCESS;
+ }
+
+ return status;
- if (option_debug > 10) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- }
- if (sscanf(s, "%lf", boost) != 1) {
- ERRORA("invalid boost <%s>\n", SKYPIAX_P_LOG, s);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return;
- }
- if (*boost < -BOOST_MAX) {
- WARNINGA("boost %s too small, using %d\n", SKYPIAX_P_LOG, s, -BOOST_MAX);
- *boost = -BOOST_MAX;
- } else if (*boost > BOOST_MAX) {
- WARNINGA("boost %s too large, using %d\n", SKYPIAX_P_LOG, s, BOOST_MAX);
- *boost = BOOST_MAX;
- }
- *boost = exp(log(10) * *boost / 20) * BOOST_SCALE;
- if (option_debug > 1)
- DEBUGA_SOUND("setting boost %s to %f\n", SKYPIAX_P_LOG, s, *boost);
}
-/*
- * returns a pointer to the descriptor with the given name
- */
-struct skypiax_pvt *skypiax_console_find_desc(char *dev)
+static switch_status_t channel_answer_channel(switch_core_session_t *session)
{
- struct skypiax_pvt *p = NULL;
- if (option_debug > 10) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- }
+ private_t *tech_pvt;
+ switch_channel_t *channel = NULL;
- for (p = skypiax_iflist; p && strcmp(p->name, dev) != 0; p = p->next);
- if (p == NULL)
- WARNINGA("could not find <%s>\n", SKYPIAX_P_LOG, dev);
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return p;
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ return SWITCH_STATUS_SUCCESS;
}
-int skypiax_console_playback_boost(int fd, int argc, char *argv[])
+
+static switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg)
{
- struct skypiax_pvt *p = skypiax_console_find_desc(skypiax_console_active);
+ switch_channel_t *channel;
+ private_t *tech_pvt;
- if (option_debug > 10) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- }
- if (argc > 2) {
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return RESULT_SHOWUSAGE;
- }
- if (!p) {
- ast_cli(fd,
- "No \"current\" skypiax_console for playback_boost, please enter 'help skypiax_console'\n");
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return RESULT_SUCCESS;
- }
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
- if (argc == 1) {
- ast_cli(fd, "playback_boost on the active skypiax_console, that is [%s], is: %5.1f\n",
- skypiax_console_active,
- 20 * log10(((double) p->playback_boost / (double) BOOST_SCALE)));
- } else if (argc == 2) {
- skypiax_store_boost(argv[1], &p->playback_boost);
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
- ast_cli(fd,
- "playback_boost on the active skypiax_console, that is [%s], is now: %5.1f\n",
- skypiax_console_active,
- 20 * log10(((double) p->playback_boost / (double) BOOST_SCALE)));
- }
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return RESULT_SUCCESS;
+ switch (msg->message_id) {
+ case SWITCH_MESSAGE_INDICATE_ANSWER:
+ channel_answer_channel(session);
+ break;
+ case SWITCH_MESSAGE_INDICATE_PROGRESS:
+ {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Engage Early Media\n");
+ switch_set_flag_locked(tech_pvt, TFLAG_IO);
+ }
+ default:
+ break;
+ }
+ return SWITCH_STATUS_SUCCESS;
}
-int skypiax_console_capture_boost(int fd, int argc, char *argv[])
-{
- struct skypiax_pvt *p = skypiax_console_find_desc(skypiax_console_active);
- if (option_debug > 10) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- }
- if (argc > 2) {
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return RESULT_SHOWUSAGE;
- }
- if (!p) {
- ast_cli(fd,
- "No \"current\" skypiax_console for capture_boost, please enter 'help skypiax_console'\n");
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return RESULT_SUCCESS;
- }
+static switch_api_interface_t channel_api_interface = {
+ /*.interface_name */ "alsa",
+ /*.desc */ "Alsa",
+ /*.function */ pa_cmd,
+ /*.syntax */ "<command> [<args>]",
+ /*.next */
+};
- if (argc == 1) {
- ast_cli(fd, "capture_boost on the active skypiax_console, that is [%s], is: %5.1f\n",
- skypiax_console_active,
- 20 * log10(((double) p->capture_boost / (double) BOOST_SCALE)));
- } else if (argc == 2) {
- skypiax_store_boost(argv[1], &p->capture_boost);
+static switch_state_handler_table_t channel_event_handlers = {
+ /*.on_init */ channel_on_init,
+ /*.on_routing */ channel_on_routing,
+ /*.on_execute */ channel_on_execute,
+ /*.on_hangup */ channel_on_hangup,
+ /*.on_exchange_media */ channel_on_exchange_media,
+ /*.on_soft_execute */ channel_on_soft_execute
+};
- ast_cli(fd,
- "capture_boost on the active skypiax_console, that is [%s], is now: %5.1f\n",
- skypiax_console_active,
- 20 * log10(((double) p->capture_boost / (double) BOOST_SCALE)));
- }
+static switch_io_routines_t channel_io_routines = {
+ /*.outgoing_channel */ channel_outgoing_channel,
+ /*.read_frame */ channel_read_frame,
+ /*.write_frame */ channel_write_frame,
+ /*.kill_channel */ channel_kill_channel,
+ /*.send_dtmf */ channel_send_dtmf,
+ /*.receive_message */ channel_receive_message
+};
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return RESULT_SUCCESS;
-}
+static switch_endpoint_interface_t channel_endpoint_interface = {
+ /*.interface_name */ "alsa",
+ /*.io_routines */ &channel_io_routines,
+ /*.event_handlers */ &channel_event_handlers,
+ /*.private */ NULL,
+ /*.next */ NULL
+};
-int skypiax_console_hangup(int fd, int argc, char *argv[])
+static switch_loadable_module_interface_t channel_module_interface = {
+ /*.module_name */ modname,
+ /*.endpoint_interface */ &channel_endpoint_interface,
+ /*.timer_interface */ NULL,
+ /*.dialplan_interface */ NULL,
+ /*.codec_interface */ NULL,
+ /*.application_interface */ NULL,
+ /*.api_interface */ &channel_api_interface
+};
+
+/* Make sure when you have 2 sessions in the same scope that you pass the appropriate one to the routines
+ that allocate memory or you will have 1 channel with memory allocated from another channel's pool!
+*/
+static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event,
+ switch_caller_profile_t *outbound_profile,
+ switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags)
{
- struct skypiax_pvt *p = skypiax_console_find_desc(skypiax_console_active);
- if (option_debug > 10) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- }
- if (argc != 1) {
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return RESULT_SHOWUSAGE;
- }
- if (!p) {
- ast_cli(fd,
- "No \"current\" skypiax_console for hanging up, please enter 'help skypiax_console'\n");
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return RESULT_SUCCESS;
- }
- if (!p->owner) {
- ast_cli(fd, "No call to hangup on the active skypiax_console, that is [%s]\n",
- skypiax_console_active);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return RESULT_FAILURE;
- }
- if (p->owner)
- ast_queue_hangup(p->owner);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return RESULT_SUCCESS;
-}
+ if ((*new_session = switch_core_session_request(&channel_endpoint_interface, pool)) != 0) {
+ private_t *tech_pvt;
+ switch_channel_t *channel;
+ switch_caller_profile_t *caller_profile;
+
+ switch_core_session_add_stream(*new_session, NULL);
+ if ((tech_pvt = (private_t *) switch_core_session_alloc(*new_session, sizeof(private_t))) != 0) {
+ memset(tech_pvt, 0, sizeof(*tech_pvt));
+ switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(*new_session));
+ channel = switch_core_session_get_channel(*new_session);
+ switch_core_session_set_private(*new_session, tech_pvt);
+ tech_pvt->session = *new_session;
+ globals.flags = GFLAG_EAR | GFLAG_MOUTH;
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Hey where is my memory pool?\n");
+ switch_core_session_destroy(new_session);
+ return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+ }
-int skypiax_console_dial(int fd, int argc, char *argv[])
-{
- char *s = NULL;
- struct skypiax_pvt *p = skypiax_console_find_desc(skypiax_console_active);
+ if (outbound_profile) {
+ char name[128];
+ const char *id = !switch_strlen_zero(outbound_profile->caller_id_number) ? outbound_profile->caller_id_number : "na";
+ snprintf(name, sizeof(name), "alsa/%s", id);
- if (option_debug > 10) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- }
- if (argc != 2) {
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return RESULT_SHOWUSAGE;
- }
- if (!p) {
- ast_cli(fd,
- "No \"current\" skypiax_console for dialing, please enter 'help skypiax_console'\n");
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return RESULT_SUCCESS;
- }
+ switch_channel_set_name(channel, name);
- if (p->owner) { /* already in a call */
- int i;
- struct ast_frame f = { AST_FRAME_DTMF, 0 };
+ caller_profile = switch_caller_profile_clone(*new_session, outbound_profile);
+ switch_channel_set_caller_profile(channel, caller_profile);
+ tech_pvt->caller_profile = caller_profile;
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Doh! no caller profile\n");
+ switch_core_session_destroy(new_session);
+ return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+ }
+
+ switch_channel_set_flag(channel, CF_OUTBOUND);
+ switch_set_flag_locked(tech_pvt, TFLAG_OUTBOUND);
+ switch_channel_set_state(channel, CS_INIT);
+ return SWITCH_CAUSE_SUCCESS;
+ }
+
+ return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
- s = argv[1];
- /* send the string one char at a time */
- for (i = 0; i < strlen(s); i++) {
- f.subclass = s[i];
- ast_queue_frame(p->owner, &f);
- }
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return RESULT_SUCCESS;
- } else
- ast_cli(fd,
- "No call in which to dial on the \"current\" skypiax_console, that is [%s]\n",
- skypiax_console_active);
- if (s)
- free(s);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return RESULT_SUCCESS;
-}
-int skypiax_console_set_active(int fd, int argc, char *argv[])
-{
- if (argc == 1)
- ast_cli(fd,
- "\"current\" skypiax_console is [%s]\n Enter 'skypiax_console show' to see the available interfaces.\n Enter 'skypiax_console interfacename' to change the \"current\" skypiax_console.\n",
- skypiax_console_active);
- else if (argc != 2) {
- return RESULT_SHOWUSAGE;
- } else {
- struct skypiax_pvt *p;
- if (strcmp(argv[1], "show") == 0) {
- ast_cli(fd, "Available interfaces:\n");
- for (p = skypiax_iflist; p; p = p->next)
- ast_cli(fd, " [%s]\n", p->name);
- return RESULT_SUCCESS;
- }
- p = skypiax_console_find_desc(argv[1]);
- if (p == NULL)
- ast_cli(fd, "Interface [%s] do not exists!\n", argv[1]);
- else {
- skypiax_console_active = p->name;
- ast_cli(fd, "\"current\" skypiax_console is now: [%s]\n", argv[1]);
- }
- }
- return RESULT_SUCCESS;
}
-int skypiax_console_skypiax(int fd, int argc, char *argv[])
+
+SWITCH_MODULE_LOAD_FUNCTION(mod_alsa_load)
{
- return RESULT_SHOWUSAGE;
-}
-/************************************************/
-#ifdef ASTERISK_VERSION_1_4
-#ifndef AST_MODULE
-#define AST_MODULE "chan_skypiax"
-#endif
-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Skypiax, Audio-Serial Driver");
-#endif /* ASTERISK_VERSION_1_4 */
+ switch_status_t status;
-/* rewriting end */
-/*******************************************************************************/
-#endif /* CHAN_SKYPIAX */
-#ifdef SKYPIAX_ADDITIONAL
+ if (switch_core_new_memory_pool(&module_pool) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "OH OH no pool\n");
+ return SWITCH_STATUS_TERM;
+ }
-//indent -gnu -ts4 -br -brs -cdw -lp -ce -nbfda -npcs -nprs -npsl -nbbo -saf -sai -saw -cs -bbo -nhnl -nut -sob -l90
-#include "skypiax.h"
-extern int skypiax_debug;
-extern char *skypiax_console_active;
-extern char skypiax_type[];
-extern struct skypiax_pvt *skypiax_iflist;
-//extern int directoriax_entry_extension;
-/* GLOBALS */
-int skypiax_dir_entry_extension=1;
-#ifdef __CYGWIN__
-struct AsteriskHandles *win32_AsteriskHandlesSkype;
-HWND win32_hInit_MainWindowHandle;
-HINSTANCE win32_hInit_ProcessHandle;
-char win32_acInit_WindowClassName[128];
-HANDLE win32_hGlobal_ThreadShutdownEvent;
-UINT win32_uiGlobal_MsgID_SkypeControlAPIAttach;
-UINT win32_uiGlobal_MsgID_SkypeControlAPIDiscover;
-HWND win32_hGlobal_SkypeAPIWindowHandle = NULL;
-DWORD win32_ulGlobal_PromptConsoleMode = 0;
-HANDLE volatile win32_hGlobal_PromptConsoleHandle = NULL;
+ if ((status = load_config()) != SWITCH_STATUS_SUCCESS) {
+ return status;
+ }
-enum {
- SKYPECONTROLAPI_ATTACH_SUCCESS = 0, /* Client is successfully
- attached and API window handle can be found
- in wParam parameter */
- SKYPECONTROLAPI_ATTACH_PENDING_AUTHORIZATION = 1, /* Skype has acknowledged
- connection request and is waiting
- for confirmation from the user. */
- /* The client is not yet attached
- * and should wait for SKYPECONTROLAPI_ATTACH_SUCCESS message */
- SKYPECONTROLAPI_ATTACH_REFUSED = 2, /* User has explicitly
- denied access to client */
- SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE = 3, /* API is not available
- at the moment.
- For example, this happens when no user
- is currently logged in. */
- /* Client should wait for
- * SKYPECONTROLAPI_ATTACH_API_AVAILABLE
- * broadcast before making any further */
- /* connection attempts. */
- SKYPECONTROLAPI_ATTACH_API_AVAILABLE = 0x8001
-};
-LRESULT APIENTRY skypiax_skype_present(HWND hWindow, UINT uiMessage, WPARAM uiParam,
- LPARAM ulParam)
-{
- LRESULT lReturnCode;
- int fIssueDefProc;
- struct skypiax_pvt *p = NULL;
- lReturnCode = 0;
- fIssueDefProc = 0;
- switch (uiMessage) {
- case WM_DESTROY:
- win32_hInit_MainWindowHandle = NULL;
- PostQuitMessage(0);
- break;
- case WM_COPYDATA:
- if (win32_hGlobal_SkypeAPIWindowHandle == (HWND) uiParam) {
+ switch_core_hash_init(&globals.call_hash, module_pool);
+ switch_mutex_init(&globals.device_lock, SWITCH_MUTEX_NESTED, module_pool);
+ switch_mutex_init(&globals.pvt_lock, SWITCH_MUTEX_NESTED, module_pool);
+ switch_mutex_init(&globals.flag_mutex, SWITCH_MUTEX_NESTED, module_pool);
- PCOPYDATASTRUCT poCopyData = (PCOPYDATASTRUCT) ulParam;
- write(win32_AsteriskHandlesSkype->fdesc[1], (const char *) poCopyData->lpData,
- strlen((const char *) poCopyData->lpData));
- write(win32_AsteriskHandlesSkype->fdesc[1], "\0", 1);
- lReturnCode = 1;
- }
- break;
- default:
- if (uiMessage == win32_uiGlobal_MsgID_SkypeControlAPIAttach) {
- switch (ulParam) {
- case SKYPECONTROLAPI_ATTACH_SUCCESS:
- NOTICA("\n\n\tConnected to Skype API!\n", SKYPIAX_P_LOG);
- win32_hGlobal_SkypeAPIWindowHandle = (HWND) uiParam;
- usleep(5000);
- win32_AsteriskHandlesSkype->win32_hGlobal_SkypeAPIWindowHandle =
- win32_hGlobal_SkypeAPIWindowHandle;
- break;
- case SKYPECONTROLAPI_ATTACH_PENDING_AUTHORIZATION:
- WARNINGA
- ("\n\n\tIf I do not immediately connect to Skype API,\n\tplease give the Skype client authorization to be connected \n\tby Asterisk and to not ask you again.\n\n",
- SKYPIAX_P_LOG);
- break;
- case SKYPECONTROLAPI_ATTACH_REFUSED:
- ERRORA("Skype client refused to be connected by Skypiax!\n", SKYPIAX_P_LOG);
- break;
- case SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE:
- ERRORA("Skype API not available\n", SKYPIAX_P_LOG);
- break;
- case SKYPECONTROLAPI_ATTACH_API_AVAILABLE:
- DEBUGA_SKYPE("Skype API available\n", SKYPIAX_P_LOG);
- break;
- default:
- WARNINGA("GOT AN UNKNOWN SKYPE WINDOWS MSG\n", SKYPIAX_P_LOG);
- }
- lReturnCode = 1;
- break;
- }
- fIssueDefProc = 1;
- break;
- }
- if (fIssueDefProc)
- lReturnCode = DefWindowProc(hWindow, uiMessage, uiParam, ulParam);
- return (lReturnCode);
+
+
+ if (switch_event_reserve_subclass(MY_EVENT_RINGING) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass!");
+ return SWITCH_STATUS_GENERR;
+ }
+
+ globals.read_frame.data = globals.databuf;
+ globals.read_frame.buflen = sizeof(globals.databuf);
+ globals.cng_frame.data = globals.cngbuf;
+ globals.cng_frame.buflen = sizeof(globals.cngbuf);
+ globals.cng_frame.datalen = sizeof(globals.cngbuf);
+ switch_set_flag((&globals.cng_frame), SFF_CNG);
+
+ /* connect my internal structure to the blank pointer passed to me */
+ *module_interface = &channel_module_interface;
+
+ /* indicate that the module should continue to be loaded */
+ return SWITCH_STATUS_SUCCESS;
}
-int win32_Initialize_CreateWindowClass(void)
+
+static switch_status_t load_config(void)
{
- unsigned char *paucUUIDString;
- RPC_STATUS lUUIDResult;
- int fReturnStatus;
- UUID oUUID;
+ char *cf = "alsa.conf";
+ switch_xml_t cfg, xml, settings, param;
+
+ if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", cf);
+ return SWITCH_STATUS_TERM;
+ }
+
+ memset(&globals, 0, sizeof(globals));
+
+
+ if ((settings = switch_xml_child(cfg, "settings"))) {
+ for (param = switch_xml_child(settings, "param"); param; param = param->next) {
+ char *var = (char *) switch_xml_attr_soft(param, "name");
+ char *val = (char *) switch_xml_attr_soft(param, "value");
+
+ if (!strcmp(var, "debug")) {
+ globals.debug = atoi(val);
+ } else if (!strcmp(var, "ring-interval")) {
+ globals.ring_interval = atoi(val);
+ } else if (!strcmp(var, "ring-file")) {
+ set_global_ring_file(val);
+ } else if (!strcmp(var, "hold-file")) {
+ set_global_hold_file(val);
+ } else if (!strcmp(var, "timer-name")) {
+ set_global_timer_name(val);
+ } else if (!strcmp(var, "device-name")) {
+ set_global_device_name(val);
+ } else if (!strcmp(var, "sample-rate")) {
+ globals.sample_rate = atoi(val);
+ } else if (!strcmp(var, "codec-ms")) {
+ int tmp = atoi(val);
+ if (SWITCH_ACCEPTABLE_INTERVAL(tmp)) {
+ globals.codec_ms = tmp;
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
+ "codec-ms must be multipe of 10 and less than %d, Using default of 20\n", SWITCH_MAX_INTERVAL);
+ }
+ } else if (!strcmp(var, "dialplan")) {
+ set_global_dialplan(val);
+ } else if (!strcmp(var, "cid-name")) {
+ set_global_cid_name(val);
+ } else if (!strcmp(var, "cid-num")) {
+ set_global_cid_num(val);
+ }
+ }
+ }
+
+ if (!globals.dialplan) {
+ set_global_dialplan("default");
+ }
+
+ if (!globals.device_name) {
+ set_global_device_name("default");
+ }
- fReturnStatus = 0;
- lUUIDResult = UuidCreate(&oUUID);
- win32_hInit_ProcessHandle =
- (HINSTANCE) OpenProcess(PROCESS_DUP_HANDLE, FALSE, GetCurrentProcessId());
- if (win32_hInit_ProcessHandle != NULL
- && (lUUIDResult == RPC_S_OK || lUUIDResult == RPC_S_UUID_LOCAL_ONLY)) {
- if (UuidToString(&oUUID, &paucUUIDString) == RPC_S_OK) {
- WNDCLASS oWindowClass;
+ if (!globals.sample_rate) {
+ globals.sample_rate = 8000;
+ }
- strcpy(win32_acInit_WindowClassName, "Skype-API-Skypiax-");
- strcat(win32_acInit_WindowClassName, (char *) paucUUIDString);
+ if (!globals.codec_ms) {
+ globals.codec_ms = 20;
+ }
- oWindowClass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
- oWindowClass.lpfnWndProc = (WNDPROC) & skypiax_skype_present;
- oWindowClass.cbClsExtra = 0;
- oWindowClass.cbWndExtra = 0;
- oWindowClass.hInstance = win32_hInit_ProcessHandle;
- oWindowClass.hIcon = NULL;
- oWindowClass.hCursor = NULL;
- oWindowClass.hbrBackground = NULL;
- oWindowClass.lpszMenuName = NULL;
- oWindowClass.lpszClassName = win32_acInit_WindowClassName;
+ if (!globals.ring_interval) {
+ globals.ring_interval = 5;
+ }
- if (RegisterClass(&oWindowClass) != 0)
- fReturnStatus = 1;
+ if (!globals.timer_name) {
+ set_global_timer_name("soft");
+ }
- RpcStringFree(&paucUUIDString);
- }
- }
- if (fReturnStatus == 0)
- CloseHandle(win32_hInit_ProcessHandle), win32_hInit_ProcessHandle = NULL;
- return (fReturnStatus);
-}
+ switch_xml_free(xml);
-void win32_DeInitialize_DestroyWindowClass(void)
-{
- UnregisterClass(win32_acInit_WindowClassName, win32_hInit_ProcessHandle);
- CloseHandle(win32_hInit_ProcessHandle), win32_hInit_ProcessHandle = NULL;
+ return SWITCH_STATUS_SUCCESS;
}
-int win32_Initialize_CreateMainWindow(void)
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_alsa_shutdown)
{
- win32_hInit_MainWindowHandle =
- CreateWindowEx(WS_EX_APPWINDOW | WS_EX_WINDOWEDGE, win32_acInit_WindowClassName, "",
- WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT,
- 128, 128, NULL, 0, win32_hInit_ProcessHandle, 0);
- return (win32_hInit_MainWindowHandle != NULL ? 1 : 0);
-}
+ deactivate_audio_device();
-void win32_DeInitialize_DestroyMainWindow(void)
-{
- if (win32_hInit_MainWindowHandle != NULL)
- DestroyWindow(win32_hInit_MainWindowHandle), win32_hInit_MainWindowHandle = NULL;
+ if (globals.read_codec.implementation) {
+ switch_core_codec_destroy(&globals.read_codec);
+ }
+
+ if (globals.write_codec.implementation) {
+ switch_core_codec_destroy(&globals.write_codec);
+ }
+ switch_core_hash_destroy(&globals.call_hash);
+
+ return SWITCH_STATUS_SUCCESS;
}
-DWORD win32_dwThreadId;
-void *do_skype_thread(void *data)
+
+static switch_status_t engage_device(unsigned int sample_rate, int codec_ms)
{
- /* create window class */
- /* create dummy/hidden window for processing messages */
- /* run message loop thread */
- /* do application control until exit */
- /* exit: send QUIT message to our own window */
- /* wait until thred terminates */
- /* destroy main window */
- /* destroy window class */
+ int err = 0;
+ snd_pcm_hw_params_t *hw_params = NULL;
+ char *device = globals.device_name;
- win32_AsteriskHandlesSkype = (struct AsteriskHandles *) data;
+ if (globals.audio_stream_in && globals.audio_stream_out) {
+ return SWITCH_STATUS_SUCCESS;
+ }
- win32_uiGlobal_MsgID_SkypeControlAPIAttach =
- RegisterWindowMessage("SkypeControlAPIAttach");
- win32_uiGlobal_MsgID_SkypeControlAPIDiscover =
- RegisterWindowMessage("SkypeControlAPIDiscover");
+ if (globals.audio_stream_in) {
+ snd_pcm_close(globals.audio_stream_in);
+ globals.audio_stream_in = NULL;
+ }
- if (win32_uiGlobal_MsgID_SkypeControlAPIAttach != 0
- && win32_uiGlobal_MsgID_SkypeControlAPIDiscover != 0) {
- if (win32_Initialize_CreateWindowClass()) {
- if (win32_Initialize_CreateMainWindow()) {
- win32_hGlobal_ThreadShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- if (win32_hGlobal_ThreadShutdownEvent != NULL) {
- if (SendMessage
- (HWND_BROADCAST, win32_uiGlobal_MsgID_SkypeControlAPIDiscover,
- (WPARAM) win32_hInit_MainWindowHandle, 0) != 0) {
- win32_AsteriskHandlesSkype->win32_hInit_MainWindowHandle =
- win32_hInit_MainWindowHandle;
- while (1) {
- MSG oMessage;
+ if (globals.audio_stream_out) {
+ snd_pcm_close(globals.audio_stream_out);
+ globals.audio_stream_out = NULL;
+ }
- while (GetMessage(&oMessage, 0, 0, 0) != FALSE) {
- TranslateMessage(&oMessage);
- DispatchMessage(&oMessage);
- }
- }
- }
- CloseHandle(win32_hGlobal_ThreadShutdownEvent);
- }
- win32_DeInitialize_DestroyMainWindow();
- }
- win32_DeInitialize_DestroyWindowClass();
- }
- }
- return NULL;
-}
+ if (!sample_rate) {
+ sample_rate = globals.sample_rate;
+ }
-#endif /* __CYGWIN__ */
+ if (!codec_ms) {
+ codec_ms = globals.codec_ms;
+ }
-#ifdef WANT_SKYPE_X11
-#define SKYPE_X11_BUF_SIZE 512
-Window skype_win = (Window) - 1;
-static XErrorHandler old_handler = 0;
-static int xerror = 0;
+ if (switch_core_codec_init(&globals.read_codec,
+ "L16",
+ NULL, sample_rate, codec_ms, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, NULL) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n");
+ return SWITCH_STATUS_FALSE;
+ } else {
+ if (switch_core_codec_init(&globals.write_codec,
+ "L16",
+ NULL,
+ sample_rate, codec_ms, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, NULL) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n");
+ switch_core_codec_destroy(&globals.read_codec);
+ return SWITCH_STATUS_FALSE;
+ }
+ }
-int X11_errors_handler(Display * dpy, XErrorEvent * err)
-{
- (void) dpy;
- struct skypiax_pvt *p = NULL;
+ if (switch_core_timer_init(&globals.timer,
+ globals.timer_name, codec_ms, globals.read_codec.implementation->samples_per_packet, module_pool) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "setup timer failed!\n");
+ switch_core_codec_destroy(&globals.read_codec);
+ switch_core_codec_destroy(&globals.write_codec);
+ return SWITCH_STATUS_FALSE;
+ }
- xerror = err->error_code;
- DEBUGA_SKYPE("Received error code %d from X Server\n", SKYPIAX_P_LOG, xerror);
- return 0; /* ignore the error */
-}
-static void X11_errors_trap(void)
-{
- xerror = 0;
- old_handler = XSetErrorHandler(X11_errors_handler);
-}
-static int X11_errors_untrap(void)
-{
- XSetErrorHandler(old_handler);
- return (xerror != BadValue) && (xerror != BadWindow);
-}
+ globals.read_frame.rate = sample_rate;
+ globals.read_frame.codec = &globals.read_codec;
-int skypiax_skype_send_message(struct AsteriskHandles *AsteriskHandlesAst,
- const char *message_P)
-{
- Window w_P;
- Display *disp;
- Window handle_P;
- struct skypiax_pvt *p = NULL;
- w_P = AsteriskHandlesAst->skype_win;
- disp = AsteriskHandlesAst->disp;
- handle_P = AsteriskHandlesAst->win;
+ switch_mutex_lock(globals.device_lock);
+ /* LOCKED ************************************************************************************************** */
- Atom atom1 = XInternAtom(disp, "SKYPECONTROLAPI_MESSAGE_BEGIN", False);
- Atom atom2 = XInternAtom(disp, "SKYPECONTROLAPI_MESSAGE", False);
- unsigned int pos = 0;
- unsigned int len = strlen(message_P);
- XEvent e;
- int ok;
- memset(&e, 0, sizeof(e));
- e.xclient.type = ClientMessage;
- e.xclient.message_type = atom1; /* leading message */
- e.xclient.display = disp;
- e.xclient.window = handle_P;
- e.xclient.format = 8;
+ if ((err = snd_pcm_open(&globals.audio_stream_out, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot open audio device %s (%s)\n", device, snd_strerror(err));
+ goto fail;
+ }
- X11_errors_trap();
- //XLockDisplay(disp);
- do {
- unsigned int i;
- for (i = 0; i < 20 && i + pos <= len; ++i)
- e.xclient.data.b[i] = message_P[i + pos];
- XSendEvent(disp, w_P, False, 0, &e);
+ if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot allocate hardware parameter structure (%s)\n", snd_strerror(err));
+ goto fail;
+ }
- e.xclient.message_type = atom2; /* following messages */
- pos += i;
- } while (pos <= len);
+ if ((err = snd_pcm_hw_params_any(globals.audio_stream_out, hw_params)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot initialize hardware parameter structure (%s)\n", snd_strerror(err));
+ goto fail;
+ }
- XSync(disp, False);
- //XUnlockDisplay(disp);
- ok = X11_errors_untrap();
+ if ((err = snd_pcm_hw_params_set_access(globals.audio_stream_out, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set access type (%s)\n", snd_strerror(err));
+ goto fail;
+ }
- if (!ok)
- DEBUGA_SKYPE("Sending message failed with status %d\n", SKYPIAX_P_LOG, xerror);
+ if ((err = snd_pcm_hw_params_set_format(globals.audio_stream_out, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set sample format (%s)\n", snd_strerror(err));
+ goto fail;
+ }
- return ok;
-}
+ if ((err = snd_pcm_hw_params_set_rate_near(globals.audio_stream_out, hw_params, &sample_rate, 0)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set sample rate (%s)\n", snd_strerror(err));
+ goto fail;
+ }
-int skypiax_skype_present(Display * disp)
-{
- Atom skype_inst = XInternAtom(disp, "_SKYPE_INSTANCE", True);
+ if ((err = snd_pcm_hw_params_set_channels(globals.audio_stream_out, hw_params, 1)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set channel count (%s)\n", snd_strerror(err));
+ goto fail;
+ }
- Atom type_ret;
- int format_ret;
- unsigned long nitems_ret;
- unsigned long bytes_after_ret;
- unsigned char *prop;
- int status;
- struct skypiax_pvt *p = NULL;
+ if ((err = snd_pcm_hw_params(globals.audio_stream_out, hw_params)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set parameters (%s)\n", snd_strerror(err));
+ goto fail;
+ }
- X11_errors_trap();
- //XLockDisplay(disp);
- status =
- XGetWindowProperty(disp, DefaultRootWindow(disp), skype_inst, 0, 1, False, XA_WINDOW,
- &type_ret, &format_ret, &nitems_ret, &bytes_after_ret, &prop);
- //XUnlockDisplay(disp);
- X11_errors_untrap();
- /* sanity check */
- if (status != Success || format_ret != 32 || nitems_ret != 1) {
- skype_win = (Window) - 1;
- DEBUGA_SKYPE("Skype instance not found\n", SKYPIAX_P_LOG);
- return 0;
- }
+ snd_pcm_hw_params_free(hw_params);
+ hw_params = NULL;
- skype_win = *(const unsigned long *) prop & 0xffffffff;
- //DEBUGA_SKYPE("Skype instance found with id #%x\n", SKYPIAX_P_LOG,
- DEBUGA_SKYPE("Skype instance found with id #%d\n", SKYPIAX_P_LOG,
- (unsigned int) skype_win);
- return 1;
-}
-void skypiax_skype_clean_disp(void *data)
-{
+ if ((err = snd_pcm_open(&globals.audio_stream_in, device, SND_PCM_STREAM_CAPTURE, 0)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot open audio device %s (%s)\n", device, snd_strerror(err));
+ goto fail;
+ }
- int *dispptr;
- int disp;
- struct skypiax_pvt *p = NULL;
+ if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot allocate hardware parameter structure (%s)\n", snd_strerror(err));
+ goto fail;
+ }
- dispptr = data;
- disp = *dispptr;
+ if ((err = snd_pcm_hw_params_any(globals.audio_stream_in, hw_params)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot initialize hardware parameter structure (%s)\n", snd_strerror(err));
+ goto fail;
+ }
- if (disp) {
- DEBUGA_SKYPE("to be destroyed disp %d\n", SKYPIAX_P_LOG, disp);
- close(disp);
- DEBUGA_SKYPE("destroyed disp\n", SKYPIAX_P_LOG);
- } else {
- DEBUGA_SKYPE("NOT destroyed disp\n", SKYPIAX_P_LOG);
- }
- DEBUGA_SKYPE("OUT destroyed disp\n", SKYPIAX_P_LOG);
- usleep(1000);
-}
-void *do_skype_thread(void *data)
-{
+ if ((err = snd_pcm_hw_params_set_access(globals.audio_stream_in, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set access type (%s)\n", snd_strerror(err));
+ goto fail;
+ }
- struct skypiax_pvt *p;
- struct AsteriskHandles *AsteriskHandlesAst;
- char buf[SKYPE_X11_BUF_SIZE];
- Display *disp = NULL;
- Window root = -1;
- Window win = -1;
+ if ((err = snd_pcm_hw_params_set_format(globals.audio_stream_in, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set sample format (%s)\n", snd_strerror(err));
+ goto fail;
+ }
+
+ if ((err = snd_pcm_hw_params_set_rate_near(globals.audio_stream_in, hw_params, &sample_rate, 0)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set sample rate (%s)\n", snd_strerror(err));
+ goto fail;
+ }
+
+ if ((err = snd_pcm_hw_params_set_channels(globals.audio_stream_in, hw_params, 1)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set channel count (%s)\n", snd_strerror(err));
+ goto fail;
+ }
+
+ if ((err = snd_pcm_hw_params_set_period_time(globals.audio_stream_in, hw_params, globals.read_codec.implementation->microseconds_per_packet, 0)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set period time (%s)\n", snd_strerror(err));
+ goto fail;
+ }
+
+ if ((err = snd_pcm_hw_params_set_period_size(globals.audio_stream_in, hw_params, globals.read_codec.implementation->samples_per_packet, 0)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set period size (%s)\n", snd_strerror(err));
+ goto fail;
+ }
+
+ if ((err = snd_pcm_hw_params(globals.audio_stream_in, hw_params)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set parameters (%s)\n", snd_strerror(err));
+ goto fail;
+ }
+
+ if (hw_params) {
+ snd_pcm_hw_params_free(hw_params);
+ hw_params = NULL;
+ }
+
+ if ((err = snd_pcm_prepare(globals.audio_stream_out)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot prepare audio interface for use (%s)\n", snd_strerror(err));
+ goto fail;
+ }
+
+ if ((err = snd_pcm_start(globals.audio_stream_out)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot start audio interface for use (%s)\n", snd_strerror(err));
+ goto fail;
+ }
- p = data;
+ if ((err = snd_pcm_prepare(globals.audio_stream_in)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot prepare audio interface for use (%s)\n", snd_strerror(err));
+ goto fail;
+ }
- if (option_debug > 10) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- }
- if (pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL)) {
- ERRORA("Unable to set cancel type to deferred\n", SKYPIAX_P_LOG);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return NULL;
- }
+ if ((err = snd_pcm_start(globals.audio_stream_in)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot start audio interface for use (%s)\n", snd_strerror(err));
+ goto fail;
+ }
- AsteriskHandlesAst = &p->AsteriskHandlesAst;
+ switch_mutex_unlock(globals.device_lock);
+ return SWITCH_STATUS_SUCCESS;
- disp = XOpenDisplay(getenv("DISPLAY"));
- if (!disp) {
- ERRORA("Cannot open X Display, exiting skype thread\n", SKYPIAX_P_LOG);
- p->skype = 0;
- p->skype_thread = AST_PTHREADT_NULL;
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return NULL;
- }
+ fail:
- int xfd;
- xfd = XConnectionNumber(disp);
- fcntl(xfd, F_SETFD, FD_CLOEXEC);
- pthread_cleanup_push(skypiax_skype_clean_disp, &xfd);
- DEBUGA_SKYPE("PUSH disp %d\n", SKYPIAX_P_LOG, xfd);
+ if (hw_params) {
+ snd_pcm_hw_params_free(hw_params);
+ hw_params = NULL;
+ }
- if (skypiax_skype_present(disp)) {
- root = DefaultRootWindow(disp);
- win =
- XCreateSimpleWindow(disp, root, 0, 0, 1, 1, 0,
- BlackPixel(disp, DefaultScreen(disp)), BlackPixel(disp,
- DefaultScreen
- (disp)));
+ switch_mutex_unlock(globals.device_lock);
- DEBUGA_SKYPE("skype_win=%d win=%d\n", SKYPIAX_P_LOG, (unsigned int) skype_win,
- (unsigned int) win);
+ if (globals.audio_stream_in) {
+ snd_pcm_close(globals.audio_stream_in);
+ }
- AsteriskHandlesAst->skype_win = skype_win;
- AsteriskHandlesAst->disp = disp;
- AsteriskHandlesAst->win = win;
+ if (globals.audio_stream_out) {
+ snd_pcm_close(globals.audio_stream_out);
+ }
- snprintf(buf, SKYPE_X11_BUF_SIZE, "NAME skypiax");
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open audio device!\n");
+ switch_core_codec_destroy(&globals.read_codec);
+ switch_core_codec_destroy(&globals.write_codec);
- if (!skypiax_skype_send_message(AsteriskHandlesAst, buf)) {
- ERRORA
- ("Sending message failed - probably Skype crashed. Please run/restart Skype manually and launch Skypiax again\n",
- SKYPIAX_P_LOG);
- p->skype = 0;
- p->skype_thread = AST_PTHREADT_NULL;
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return NULL;
- }
+ return SWITCH_STATUS_FALSE;
- snprintf(buf, SKYPE_X11_BUF_SIZE, "PROTOCOL 6");
- if (!skypiax_skype_send_message(AsteriskHandlesAst, buf)) {
- ERRORA
- ("Sending message failed - probably Skype crashed. Please run/restart Skype manually and launch Skypiax again\n",
- SKYPIAX_P_LOG);
- p->skype = 0;
- p->skype_thread = AST_PTHREADT_NULL;
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return NULL;
- }
- /* perform an events loop */
- XEvent an_event;
- char buf[21]; /* can't be longer */
- char buffer[17000];
- char *b;
- int i;
- b = buffer;
+}
- while (1) {
- pthread_testcancel();
- XNextEvent(disp, &an_event);
- switch (an_event.type) {
- case ClientMessage:
+static switch_status_t dtmf_call(char **argv, int argc, switch_stream_handle_t *stream)
+{
+ char *dtmf_str = argv[0];
+ switch_dtmf_t dtmf = { 0, switch_core_default_dtmf_duration(0) };
- if (an_event.xclient.format != 8)
- break;
+ if (switch_strlen_zero(dtmf_str)) {
+ stream->write_function(stream, "No DTMF Supplied!\n");
+ } else {
+ switch_mutex_lock(globals.pvt_lock);
+ if (globals.call_list) {
+ switch_channel_t *channel = switch_core_session_get_channel(globals.call_list->session);
+ char *p = dtmf_str;
+ while (p && *p) {
+ dtmf.digit = *p;
+ switch_channel_queue_dtmf(channel, &dtmf);
+ p++;
+ }
+ }
+ switch_mutex_unlock(globals.pvt_lock);
+ }
- for (i = 0; i < 20 && an_event.xclient.data.b[i] != '\0'; ++i)
- buf[i] = an_event.xclient.data.b[i];
+ return SWITCH_STATUS_SUCCESS;
+}
- buf[i] = '\0';
+static switch_status_t switch_call(char **argv, int argc, switch_stream_handle_t *stream)
+{
+ private_t *tp, *tech_pvt = NULL;
+ char *callid = argv[0];
+ uint8_t one_call = 0;
+
+ switch_mutex_lock(globals.pvt_lock);
+ if (switch_strlen_zero(callid)) {
+ if (globals.call_list) {
+ if (globals.call_list->next) {
+ tech_pvt = globals.call_list->next;
+ } else {
+ tech_pvt = globals.call_list;
+ one_call = 1;
+ }
+ }
+ } else if (!strcasecmp(callid, "none")) {
+ for (tp = globals.call_list; tp; tp = tp->next) {
+ switch_clear_flag_locked(tp, TFLAG_MASTER);
+ }
+ stream->write_function(stream, "OK\n");
+ goto done;
+ } else {
+ tech_pvt = switch_core_hash_find(globals.call_hash, callid);
+ }
- //NOTICA("ClientMessage buf:|||%s||| buffer:|||%s||| serial=%ld|||\r\n",SKYPIAX_P_LOG,buf, buffer,an_event.xclient.serial);
- //NOTICA ("SKYPE read: |||%s|||%d\n", SKYPIAX_P_LOG, buf, strlen(buf));
- //NOTICA ("SKYPE buffer: |||%s|||%d\n", SKYPIAX_P_LOG, buffer, strlen(buffer));
+ if (tech_pvt) {
+ if (tech_pvt == globals.call_list && !tech_pvt->next) {
+ one_call = 1;
+ }
- strcat(buffer, buf);
+ if (!one_call) {
+ remove_pvt(tech_pvt);
+ }
+ add_pvt(tech_pvt, PA_MASTER);
+ stream->write_function(stream, "OK\n");
+ } else {
+ stream->write_function(stream, "NO SUCH CALL\n");
+ }
- if (i < 20) { /* last fragment */
- write(AsteriskHandlesAst->fdesc[1], b, strlen(b) + 1);
- //write(AsteriskHandlesAst->fdesc[1], "\0", 1);
- DEBUGA_SKYPE("SKYPE pipewrite: |||%s|||len=%d serial=%ld\n", SKYPIAX_P_LOG, b,
- strlen(b) + 1, an_event.xclient.serial);
- //usleep(1000);
- memset(buffer, '\0', 17000);
- }
+ done:
+ switch_mutex_unlock(globals.pvt_lock);
- break;
- default:
- break;
- }
- }
- } else {
- ERRORA
- ("Skype is not running, maybe crashed. Please run/restart Skype and relaunch Skypiax\n",
- SKYPIAX_P_LOG);
- p->skype = 0;
- p->skype_thread = AST_PTHREADT_NULL;
- return NULL;
- }
- p->skype = 0;
- p->skype_thread = AST_PTHREADT_NULL;
- pthread_cleanup_pop(1);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return NULL;
+ return SWITCH_STATUS_SUCCESS;
}
-#endif /* WANT_SKYPE_X11 */
-
-int skypiax_skype_read(struct skypiax_pvt *p)
+static switch_status_t hangup_call(char **argv, int argc, switch_stream_handle_t *stream)
{
+ private_t *tech_pvt;
+ char *callid = argv[0];
- char read_from_pipe[4096];
- char messaggio[4096];
- char messaggio_2[4096];
- char *buf, obj[512] = "", id[512] = "", prop[512] = "", value[512] = "", *where;
- char **stringp = NULL;
- int fd;
- int rt;
- fd_set fs;
- struct timeval to;
- int howmany, i, a;
+ switch_mutex_lock(globals.pvt_lock);
+ if (switch_strlen_zero(callid)) {
+ tech_pvt = globals.call_list;
+ } else {
+ tech_pvt = switch_core_hash_find(globals.call_hash, callid);
+ }
- if (option_debug > 100) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- }
- memset(read_from_pipe, 0, 4096);
- memset(messaggio, 0, 4096);
- memset(messaggio_2, 0, 4096);
+ if (tech_pvt) {
+ switch_channel_hangup(switch_core_session_get_channel(tech_pvt->session), SWITCH_CAUSE_NORMAL_CLEARING);
+ //switch_set_flag_locked(tech_pvt, TFLAG_HUP);
+ stream->write_function(stream, "OK\n");
+ } else {
+ stream->write_function(stream, "NO SUCH CALL\n");
+ }
+ switch_mutex_unlock(globals.pvt_lock);
- fd = p->AsteriskHandlesAst.fdesc[0];
- FD_ZERO(&fs);
- FD_SET(fd, &fs);
- to.tv_usec = 100;
- to.tv_sec = 0;
- rt = select(fd + 1, &fs, NULL, NULL, &to);
- if (rt > 0) {
- howmany =
- read(p->AsteriskHandlesAst.fdesc[0], read_from_pipe, sizeof(read_from_pipe));
+ return SWITCH_STATUS_SUCCESS;
- a = 0;
- for (i = 0; i < howmany; i++) {
- messaggio[a] = read_from_pipe[i];
- a++;
+}
- if (read_from_pipe[i] == '\0') {
+static switch_status_t answer_call(char **argv, int argc, switch_stream_handle_t *stream)
+{
+ private_t *tp;
+ int x = 0;
+ char *callid = argv[0];
- if (option_debug > 1)
- DEBUGA_SKYPE("read_skype: howmany=%d, i=%d, a=%d, |||%s||| \n", SKYPIAX_P_LOG,
- howmany, i, a, messaggio);
+ switch_mutex_lock(globals.pvt_lock);
-#if 0 //FIXME wat's the use of this?
- if (!strcasecmp(messaggio, "ERROR 68")) { /* not yet protocol specified,
- just authorized */
- NOTICA
- ("Please give the Skype client authorization to be connected by Skypiax (and to not ask you again)\n",
- SKYPIAX_P_LOG);
- sleep(1);
- skypiax_skype_write(p, "PROTOCOL 6");
- usleep(10000);
- }
-#endif
+ if (!switch_strlen_zero(callid)) {
+ if ((tp = switch_core_hash_find(globals.call_hash, callid))) {
+ if (switch_test_flag(tp, TFLAG_ANSWER)) {
+ stream->write_function(stream, "CALL ALREADY ANSWERED\n");
+ } else {
+ switch_channel_t *channel = switch_core_session_get_channel(tp->session);
+ switch_set_flag_locked(tp, TFLAG_ANSWER);
+ switch_channel_answer(channel);
+ add_pvt(tp, PA_MASTER);
+ }
+ } else {
+ stream->write_function(stream, "NO SUCH CALL\n");
+ }
- if (!strncasecmp(messaggio, "ERROR 92 CALL", 12)) {
- ERRORA
- ("Skype got ERROR: |||%s|||, the number we called was not recognized\n",
- SKYPIAX_P_LOG, messaggio);
- p->skype_callflow = CALLFLOW_STATUS_FINISHED;
- if (option_debug)
- DEBUGA_SKYPE("skype_call now is DOWN\n", SKYPIAX_P_LOG);
- p->skype_call_id[0] = '\0';
+ goto done;
+ }
- if (p->interface_state != AST_STATE_HANGUP_REQUESTED) {
- if (option_debug > 100) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- p->interface_state = AST_STATE_DOWN;
- if(p->owner)
- p->owner->hangupcause = AST_CAUSE_NORMAL;
- return CALLFLOW_INCOMING_HANGUP;
- } else {
- p->interface_state = AST_STATE_DOWN;
- }
- }
+ for (tp = globals.call_list; tp; tp = tp->next) {
+ if (!switch_test_flag(tp, TFLAG_ANSWER)) {
+ switch_channel_t *channel = switch_core_session_get_channel(tp->session);
+ switch_set_flag_locked(tp, TFLAG_ANSWER);
+ switch_channel_answer(channel);
+ add_pvt(tp, PA_MASTER);
+ x++;
+ break;
+ }
+ }
+ done:
+ switch_mutex_unlock(globals.pvt_lock);
- strncpy(messaggio_2, messaggio, sizeof(messaggio) - 1);
+ stream->write_function(stream, "Answered %d channels.\n", x);
- buf = messaggio;
- stringp = &buf;
- where = strsep(stringp, " ");
- if (!where) {
- WARNINGA("Skype MSG without spaces: %s\n", SKYPIAX_P_LOG, messaggio);
- }
- if (!strcasecmp(messaggio, "#333")) {
- /* DEBUGA_SKYPE("Skype MSG: messaggio_2: %s, messaggio2[11]: %s\n", SKYPIAX_P_LOG,
- * messaggio_2, &messaggio_2[11]); */
- memset(p->skype_friends, 0, 4096);
- strncpy(p->skype_friends, &messaggio_2[11], 4095);
- }
- if (!strcasecmp(messaggio, "#222")) {
- /* DEBUGA_SKYPE("Skype MSG: messaggio_2: %s, messaggio2[10]: %s\n", SKYPIAX_P_LOG,
- * messaggio_2, &messaggio_2[10]); */
- memset(p->skype_fullname, 0, 512);
- strncpy(p->skype_fullname, &messaggio_2[10], 511);
- }
- if (!strcasecmp(messaggio, "#765")) {
- /* DEBUGA_SKYPE("Skype MSG: messaggio_2: %s, messaggio2[10]: %s\n", SKYPIAX_P_LOG,
- * messaggio_2, &messaggio_2[10]); */
- memset(p->skype_displayname, 0, 512);
- strncpy(p->skype_displayname, &messaggio_2[10], 511);
- }
- if (!strcasecmp(messaggio, "ERROR")) {
- ERRORA
- ("Skype got ERROR: |||%s|||\n",
- SKYPIAX_P_LOG, messaggio);
- p->skype_callflow = CALLFLOW_STATUS_FINISHED;
- if (option_debug)
- DEBUGA_SKYPE("skype_call now is DOWN\n", SKYPIAX_P_LOG);
- p->skype_call_id[0] = '\0';
+ return SWITCH_STATUS_SUCCESS;
+
+}
+
+static switch_status_t do_flags(char **argv, int argc, switch_stream_handle_t *stream)
+{
+ char *action = argv[0];
+ char *flag_str = argv[1];
+ GFLAGS flags = GFLAG_NONE;
+ char *p;
+ int x = 0;
+
+ if (argc < 2) {
+ goto desc;
+ }
- if (p->interface_state != AST_STATE_HANGUP_REQUESTED) {
- if (option_debug > 100) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- p->interface_state = AST_STATE_DOWN;
- if(p->owner){
- p->owner->hangupcause = AST_CAUSE_NORMAL;
- }
- return CALLFLOW_INCOMING_HANGUP;
- } else {
- p->interface_state = AST_STATE_DOWN;
- }
- }
- if (!strcasecmp(messaggio, "CALL")) {
+ for (x = 1; x < argc; x++) {
+ flag_str = argv[x];
+ for (p = flag_str; *p; p++) {
+ *p = (char) tolower(*p);
+ }
- strncpy(obj, where, sizeof(obj) - 1);
+ if (strstr(flag_str, "ear")) {
+ flags |= GFLAG_EAR;
+ }
+ if (strstr(flag_str, "mouth")) {
+ flags |= GFLAG_MOUTH;
+ }
+ }
- where = strsep(stringp, " ");
+ if (!strcasecmp(action, "on")) {
+ if (flags & GFLAG_EAR) {
+ switch_set_flag((&globals), GFLAG_EAR);
+ }
+ if (flags & GFLAG_MOUTH) {
+ switch_set_flag((&globals), GFLAG_MOUTH);
+ }
+ } else if (!strcasecmp(action, "off")) {
+ if (flags & GFLAG_EAR) {
+ switch_clear_flag((&globals), GFLAG_EAR);
+ }
+ if (flags & GFLAG_MOUTH) {
+ switch_clear_flag((&globals), GFLAG_MOUTH);
+ }
+ } else {
+ goto bad;
+ }
- strncpy(id, where, sizeof(id) - 1);
+ desc:
+ x = 0;
+ stream->write_function(stream, "FLAGS: ");
+ if (switch_test_flag((&globals), GFLAG_EAR)) {
+ stream->write_function(stream, "ear");
+ x++;
+ }
+ if (switch_test_flag((&globals), GFLAG_MOUTH)) {
+ stream->write_function(stream, "%smouth", x ? "|" : "");
+ x++;
+ }
+ if (!x) {
+ stream->write_function(stream, "none");
+ }
- where = strsep(stringp, " ");
+ goto done;
- strncpy(prop, where, sizeof(prop) - 1);
+ bad:
+ stream->write_function(stream, "Usage: flags [on|off] <flags>\n");
+ done:
+ return SWITCH_STATUS_SUCCESS;
+}
- where = strsep(stringp, " ");
+static switch_status_t list_calls(char **argv, int argc, switch_stream_handle_t *stream)
+{
+ private_t *tp;
+ int x = 0;
+ const char *cid_name = "n/a";
+ const char *cid_num = "n/a";
- strncpy(value, where, sizeof(value) - 1);
+ switch_mutex_lock(globals.pvt_lock);
+ for (tp = globals.call_list; tp; tp = tp->next) {
+ switch_channel_t *channel;
+ switch_caller_profile_t *profile;
+ x++;
+ channel = switch_core_session_get_channel(tp->session);
+
+ if ((profile = switch_channel_get_caller_profile(channel))) {
+ if (profile->originatee_caller_profile) {
+ cid_name = "Outbound Call";
+ cid_num = profile->originatee_caller_profile->destination_number;
+ } else {
+ cid_name = profile->caller_id_name;
+ cid_num = profile->caller_id_number;
+ }
+ }
- where = strsep(stringp, " ");
+ stream->write_function(stream, "%s %s [%s (%s)] %s\n", tp->call_id, switch_channel_get_name(channel),
+ cid_name, cid_num, switch_test_flag(tp, TFLAG_MASTER) ? "active" : "hold");
+ }
+ switch_mutex_unlock(globals.pvt_lock);
- if (option_debug > 1)
- DEBUGA_SKYPE
- ("Skype MSG: messaggio: %s, obj: %s, id: %s, prop: %s, value: %s,where: %s!\n",
- SKYPIAX_P_LOG, messaggio, obj, id, prop, value, where ? where : "NULL");
+ stream->write_function(stream, "\n%d call%s\n", x, x == 1 ? "" : "s");
- if (!strcasecmp(prop, "PARTNER_HANDLE")) {
- strncpy(p->callid_number, value, sizeof(p->callid_number) - 1);
- return CALLFLOW_INCOMING_RING;
- }
- if (!strcasecmp(prop, "PARTNER_DISPNAME")) {
- snprintf(p->callid_name, sizeof(p->callid_name) - 1, "%s%s%s", value,
- where ? " " : "", where ? where : "");
- }
- if (!strcasecmp(prop, "CONF_ID") && !strcasecmp(value, "0")) {
- DEBUGA_SKYPE("the skype_call %s is NOT a conference call\n", SKYPIAX_P_LOG,
- id);
- if (p->interface_state == AST_STATE_DOWN)
- p->interface_state = AST_STATE_PRERING;
- }
- if (!strcasecmp(prop, "CONF_ID") && strcasecmp(value, "0")) {
- DEBUGA_SKYPE("the skype_call %s is a conference call\n", SKYPIAX_P_LOG, id);
- if (p->interface_state == AST_STATE_DOWN)
- p->interface_state = AST_STATE_PRERING;
- }
+ return SWITCH_STATUS_SUCCESS;
+}
- if (!strcasecmp(prop, "DTMF")) {
- struct ast_frame f2 = { AST_FRAME_DTMF, value[0], };
- DEBUGA_SKYPE("Call %s received a DTMF: %s\n", SKYPIAX_P_LOG, id, value);
- ast_queue_frame(p->owner, &f2);
- }
+static switch_status_t place_call(char **argv, int argc, switch_stream_handle_t *stream)
+{
+ switch_core_session_t *session;
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+ char *dest = NULL;
- if (!strcasecmp(prop, "FAILUREREASON")) {
- /* if (option_debug > 1) */
- DEBUGA_SKYPE
- ("Skype has FAILED on skype_call %s. Let's wait for the FAILED message.\n",
- SKYPIAX_P_LOG, id);
- }
- if (!strcasecmp(prop, "DURATION") && (!strcasecmp(value, "1"))) {
- if (strcasecmp(id, p->skype_call_id)) {
- strncpy(p->skype_call_id, id, sizeof(p->skype_call_id) - 1);
- if (option_debug > 1)
- DEBUGA_SKYPE
- ("We called a Skype contact and he answered us on skype_call: %s.\n",
- SKYPIAX_P_LOG, id);
- }
- }
+ if (!argv[0]) {
+ stream->write_function(stream, "FAIL:Usage: call <dest>\n");
+ return SWITCH_STATUS_SUCCESS;
+ }
+ dest = argv[0];
+ if ((session = switch_core_session_request(&channel_endpoint_interface, NULL)) != 0) {
+ private_t *tech_pvt;
+ switch_channel_t *channel;
+ char *dialplan = globals.dialplan;
+ char *cid_name = globals.cid_name;
+ char *cid_num = globals.cid_num;
+ char ip[25] = "0.0.0.0";
- if (!strcasecmp(prop, "STATUS")) {
- if (!strcasecmp(value, "RINGING")) {
- char msg_to_skype[1024];
- if (p->interface_state != AST_STATE_DIALING) {
- /* we are not calling out */
+ switch_core_session_add_stream(session, NULL);
+ if ((tech_pvt = (private_t *) switch_core_session_alloc(session, sizeof(private_t))) != 0) {
+ memset(tech_pvt, 0, sizeof(*tech_pvt));
+ switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
+ channel = switch_core_session_get_channel(session);
+ switch_core_session_set_private(session, tech_pvt);
+ tech_pvt->session = session;
+ globals.flags = GFLAG_EAR | GFLAG_MOUTH;
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Hey where is my memory pool?\n");
+ switch_core_session_destroy(&session);
+ return SWITCH_STATUS_MEMERR;
+ }
- if (!p->owner) {
- /* we are not inside an active call */
- p->skype_callflow = CALLFLOW_STATUS_RINGING;
- p->interface_state = AST_STATE_RING;
- /* no owner, no active call, let's answer */
- skypiax_skype_write(p, "SET AGC OFF");
- usleep(10000);
- skypiax_skype_write(p, "SET AEC OFF");
- usleep(10000);
- sprintf(msg_to_skype, "GET CALL %s PARTNER_DISPNAME", id);
- skypiax_skype_write(p, msg_to_skype);
- usleep(10000);
- sprintf(msg_to_skype, "GET CALL %s PARTNER_HANDLE", id);
- skypiax_skype_write(p, msg_to_skype);
- usleep(10000);
- sprintf(msg_to_skype, "ALTER CALL %s ANSWER", id);
- skypiax_skype_write(p, msg_to_skype);
- if (option_debug)
- DEBUGA_SKYPE("We answered a Skype RING on skype_call %s\n",
- SKYPIAX_P_LOG, id);
- strncpy(p->skype_call_id, id, sizeof(p->skype_call_id) - 1);
- } else {
- /* we're owned, we're in a call, let's refuse */
- sprintf(msg_to_skype, "SET CALL %s STATUS FINISHED", id);
- skypiax_skype_write(p, msg_to_skype);
- usleep(10000);
- DEBUGA_SKYPE
- ("We have NOT answered a Skype RING on skype_call %s, because we are already in a skypiax call\n",
- SKYPIAX_P_LOG, id);
+ if (!switch_strlen_zero(argv[1])) {
+ dialplan = argv[1];
+ }
- }
- } else {
- /* we are calling out */
- p->skype_callflow = CALLFLOW_STATUS_RINGING;
- p->interface_state = AST_STATE_RINGING;
- ast_queue_control(p->owner, AST_CONTROL_RINGING);
- strncpy(p->skype_call_id, id, sizeof(p->skype_call_id) - 1);
- DEBUGA_SKYPE("Our remote party in skype_call %s is RINGING\n",
- SKYPIAX_P_LOG, id);
- }
- } else if (!strcasecmp(value, "EARLYMEDIA")) {
- p->skype_callflow = CALLFLOW_STATUS_EARLYMEDIA;
- p->interface_state = AST_STATE_DIALING;
- ast_queue_control(p->owner, AST_CONTROL_RINGING);
- DEBUGA_SKYPE("Our remote party in skype_call %s is EARLYMEDIA\n",
- SKYPIAX_P_LOG, id);
- } else if (!strcasecmp(value, "MISSED")) {
- DEBUGA_SKYPE("We missed skype_call %s\n", SKYPIAX_P_LOG, id);
+ if (!switch_strlen_zero(argv[2])) {
+ cid_num = argv[2];
+ }
- } else if (!strcasecmp(value, "FINISHED")) {
- p->skype_callflow = CALLFLOW_STATUS_FINISHED;
- if (option_debug)
- DEBUGA_SKYPE("skype_call %s now is DOWN\n", SKYPIAX_P_LOG, id);
- p->skype_call_id[0] = '\0';
+ if (!switch_strlen_zero(argv[3])) {
+ cid_name = argv[3];
+ }
- if (p->interface_state != AST_STATE_HANGUP_REQUESTED) {
- if (option_debug > 100) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- p->interface_state = AST_STATE_DOWN;
- if(p->owner)
- p->owner->hangupcause = AST_CAUSE_NORMAL;
- return CALLFLOW_INCOMING_HANGUP;
- } else {
- p->interface_state = AST_STATE_DOWN;
- }
+ if (!switch_strlen_zero(argv[4])) {
+ tech_pvt->sample_rate = atoi(argv[4]);
+ }
- } else if (!strcasecmp(value, "CANCELLED")) {
- p->skype_callflow = CALLFLOW_STATUS_CANCELLED;
- if (option_debug)
- DEBUGA_SKYPE
- ("we tried to call Skype on skype_call %s and Skype has now CANCELLED\n",
- SKYPIAX_P_LOG, id);
- p->skype_call_id[0] = '\0';
+ if (!switch_strlen_zero(argv[5])) {
+ tech_pvt->codec_ms = atoi(argv[5]);
+ }
- if (p->interface_state != AST_STATE_HANGUP_REQUESTED) {
- if (option_debug > 100) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- p->interface_state = AST_STATE_DOWN;
- if(p->owner)
- p->owner->hangupcause = AST_CAUSE_NORMAL;
- return CALLFLOW_INCOMING_HANGUP;
- } else {
- p->interface_state = AST_STATE_DOWN;
- }
- } else if (!strcasecmp(value, "FAILED")) {
- p->skype_callflow = CALLFLOW_STATUS_FAILED;
- if (option_debug)
- DEBUGA_SKYPE
- ("we tried to call Skype on skype_call %s and Skype has now FAILED\n",
- SKYPIAX_P_LOG, id);
- p->skype_call_id[0] = '\0';
- strncpy(p->skype_call_id, id, sizeof(p->skype_call_id) - 1);
- p->interface_state = AST_STATE_DOWN;
- if (option_debug > 100) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- if(p->owner)
- p->owner->hangupcause = AST_CAUSE_NORMAL;
- return CALLFLOW_INCOMING_HANGUP;
- } else if (!strcasecmp(value, "REFUSED")) {
- if (!strcasecmp(id, p->skype_call_id)) {
- /* this is the id of the call we are in, probably we generated it */
- p->skype_callflow = CALLFLOW_STATUS_REFUSED;
- if (option_debug)
- DEBUGA_SKYPE
- ("we tried to call Skype on skype_call %s and Skype has now REFUSED\n",
- SKYPIAX_P_LOG, id);
- strncpy(p->skype_call_id, id, sizeof(p->skype_call_id) - 1);
- p->interface_state = AST_STATE_DOWN;
- p->skype_call_id[0] = '\0';
- if (option_debug > 100) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- if(p->owner)
- p->owner->hangupcause = AST_CAUSE_NORMAL;
- return CALLFLOW_INCOMING_HANGUP;
- } else {
- /* we're here because were us that refused an incoming call */
- DEBUGA_SKYPE("we REFUSED skype_call %s\n", SKYPIAX_P_LOG, id);
+ switch_find_local_ip(ip, sizeof(ip), AF_INET);
- }
- } else if (!strcasecmp(value, "ROUTING")) {
- p->skype_callflow = CALLFLOW_STATUS_ROUTING;
- p->interface_state = AST_STATE_DIALING;
- strncpy(p->skype_call_id, id, sizeof(p->skype_call_id) - 1);
- DEBUGA_SKYPE("skype_call: %s is now ROUTING\n", SKYPIAX_P_LOG, id);
- } else if (!strcasecmp(value, "UNPLACED")) {
- p->skype_callflow = CALLFLOW_STATUS_UNPLACED;
- p->interface_state = AST_STATE_DIALING;
- strncpy(p->skype_call_id, id, sizeof(p->skype_call_id) - 1);
- DEBUGA_SKYPE("skype_call: %s is now UNPLACED\n", SKYPIAX_P_LOG, id);
- } else if (!strcasecmp(value, "INPROGRESS")) {
- p->skype_callflow = CALLFLOW_STATUS_INPROGRESS;
- strncpy(p->skype_call_id, id, sizeof(p->skype_call_id) - 1);
- p->interface_state = AST_STATE_UP;
- if (option_debug > 1)
- DEBUGA_SKYPE("skype_call: %s is now active\n", SKYPIAX_P_LOG, id);
+ if ((tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session),
+ NULL,
+ dialplan, cid_name, cid_num, ip, NULL, NULL, NULL, (char *) modname, NULL, dest)) != 0) {
+ char name[128];
+ snprintf(name, sizeof(name), "alsa/%s", tech_pvt->caller_profile->destination_number ? tech_pvt->caller_profile->destination_number : modname);
+ switch_channel_set_name(channel, name);
+
+ switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
+ }
+ tech_pvt->session = session;
+ if ((status = engage_device(tech_pvt->sample_rate, tech_pvt->codec_ms)) == SWITCH_STATUS_SUCCESS) {
+ switch_set_flag_locked(tech_pvt, TFLAG_ANSWER);
+ switch_channel_mark_answered(channel);
+ switch_channel_set_state(channel, CS_INIT);
+
+ if (switch_core_session_thread_launch(tech_pvt->session) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error spawning thread\n");
+ switch_core_session_destroy(&session);
+ stream->write_function(stream, "FAIL:Thread Error!\n");
+ } else {
+ add_pvt(tech_pvt, PA_MASTER);
+ stream->write_function(stream, "SUCCESS:%s:%s\n", tech_pvt->call_id, switch_core_session_get_uuid(tech_pvt->session));
+ }
+ } else {
+ switch_core_session_destroy(&session);
+ stream->write_function(stream, "FAIL:Device Error!\n");
+ }
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_STANDARD_API(pa_cmd)
+{
+ char *argv[1024] = { 0 };
+ int argc = 0;
+ char *mycmd = NULL;
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+ pa_command_t func = NULL;
+ int lead = 1;
+ char *wcmd = NULL, *action = NULL;
+ char cmd_buf[1024] = "";
+ char *http = NULL;
+
+ if (stream->param_event) {
+ http = switch_event_get_header(stream->param_event, "http-host");
+ }
+
+
+ const char *usage_string = "USAGE:\n"
+ "--------------------------------------------------------------------------------\n"
+ "alsa help\n"
+ "alsa call <dest> [<dialplan> <cid_name> <cid_num> <rate>]\n"
+ "alsa answer [<call_id>]\n"
+ "alsa hangup [<call_id>]\n"
+ "alsa list\n"
+ "alsa switch [<call_id>|none]\n"
+ "alsa dtmf <digit string>\n"
+ "alsa flags [on|off] [ear] [mouth]\n" "--------------------------------------------------------------------------------\n";
- if (p->owner) {
- ast_queue_control(p->owner, AST_CONTROL_ANSWER);
- }
- if (option_debug > 1)
- DEBUGA_SKYPE("skype_call: %s AST_CONTROL_ANSWER sent\n", SKYPIAX_P_LOG,
- id);
+ if (http) {
+#if 0
+ switch_event_header_t *hp;
+ stream->write_function(stream, "<pre>");
+ for (hp = stream->param_event->headers; hp; hp = hp->next) {
+ stream->write_function(stream, "[%s]=[%s]\n", hp->name, hp->value);
+ }
+ stream->write_function(stream, "</pre>");
+#endif
- if (p->owner) {
- char msg_to_skype[1024];
- if (!p->tcp_cli_thread) {
- if (ast_pthread_create
- (&p->tcp_cli_thread, NULL, skypiax_do_tcp_cli_thread, p) < 0) {
- ERRORA("Unable to start tcp_cli_thread thread.\n", SKYPIAX_P_LOG);
- if (option_debug > 100) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return -1;
- } else {
- DEBUGA_SKYPE("started tcp_cli_thread thread.\n", SKYPIAX_P_LOG);
- }
- }
+ stream->write_function(stream, "Content-type: text/html\n\n");
- usleep(100000);
- sprintf(msg_to_skype, "ALTER CALL %s SET_OUTPUT PORT=\"5556\"", id);
- skypiax_skype_write(p, msg_to_skype);
- usleep(100000);
- sprintf(msg_to_skype, "ALTER CALL %s SET_INPUT PORT=\"5558\"", id);
- skypiax_skype_write(p, msg_to_skype);
- usleep(100000);
- }
+ wcmd = switch_str_nil(switch_event_get_header(stream->param_event, "wcmd"));
+ action = switch_event_get_header(stream->param_event, "action");
- p->skype_callflow = AST_STATE_UP;
- } else {
- WARNINGA("skype_call: %s, STATUS: %s is not recognized\n", SKYPIAX_P_LOG,
- id, value);
+ if (action) {
+ if (strlen(action) == 1) {
+ snprintf(cmd_buf, sizeof(cmd_buf), "dtmf %s", action);
+ cmd = cmd_buf;
+ } else if (!strcmp(action, "mute")) {
+ snprintf(cmd_buf, sizeof(cmd_buf), "flags off mouth");
+ cmd = cmd_buf;
+ } else if (!strcmp(action, "unmute")) {
+ snprintf(cmd_buf, sizeof(cmd_buf), "flags on mouth");
+ cmd = cmd_buf;
+ } else if (!strcmp(action, "switch")) {
+ snprintf(cmd_buf, sizeof(cmd_buf), "switch %s", wcmd);
+ cmd = cmd_buf;
+ } else if (!strcmp(action, "call")) {
+ snprintf(cmd_buf, sizeof(cmd_buf), "call %s", wcmd);
+ cmd = cmd_buf;
+ } else if (!strcmp(action, "hangup") || !strcmp(action, "list") || !strcmp(action, "answer")) {
+ cmd = action;
+ }
+ }
- }
- } //STATUS
+ if (switch_strlen_zero(cmd)) {
+ goto done;
+ }
- } //CALL
+ } else {
- a = 0;
- } //message end
- } //read_from_pipe
+ if (switch_strlen_zero(cmd)) {
+ stream->write_function(stream, "%s", usage_string);
+ goto done;
+ }
+ }
- }
+ if (!(mycmd = strdup(cmd))) {
+ status = SWITCH_STATUS_MEMERR;
+ goto done;
+ }
- if (option_debug > 100) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return 0;
-}
+ if (!(argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
+ stream->write_function(stream, "%s", usage_string);
+ goto done;
+ }
-int skypiax_skype_write(struct skypiax_pvt *p, char *msg_to_skype)
-{
-#ifdef __CYGWIN__
- static char acInputRow[1024];
- COPYDATASTRUCT oCopyData;
+ if (!strcasecmp(argv[0], "call")) {
+ func = place_call;
+ } else if (!strcasecmp(argv[0], "help")) {
+ stream->write_function(stream, "%s", usage_string);
+ goto done;
+ } else if (!strcasecmp(argv[0], "list")) {
+ func = list_calls;
+ } else if (!strcasecmp(argv[0], "flags")) {
+ func = do_flags;
+ } else if (!strcasecmp(argv[0], "hangup")) {
+ func = hangup_call;
+ } else if (!strcasecmp(argv[0], "answer")) {
+ func = answer_call;
+ } else if (!strcasecmp(argv[0], "switch")) {
+ func = switch_call;
+ } else if (!strcasecmp(argv[0], "dtmf")) {
+ func = dtmf_call;
+ }
- if (option_debug > 100) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- }
- sprintf(acInputRow, "%s", msg_to_skype);
- if (option_debug > 1)
- DEBUGA_SKYPE("acInputRow: |||%s||||\n", SKYPIAX_P_LOG, acInputRow);
- /* send command to skype */
- oCopyData.dwData = 0;
- oCopyData.lpData = acInputRow;
- oCopyData.cbData = strlen(acInputRow) + 1;
- if (oCopyData.cbData != 1) {
- if (SendMessage
- (p->AsteriskHandlesAst.win32_hGlobal_SkypeAPIWindowHandle, WM_COPYDATA,
- (WPARAM) p->AsteriskHandlesAst.win32_hInit_MainWindowHandle,
- (LPARAM) & oCopyData) == FALSE) {
- ERRORA
- ("Sending message failed - probably Skype crashed.\n\nPlease shutdown Skypiax (Asterisk), then restart Skype from the menu, then launch Skypiax and try again.\n",
- SKYPIAX_P_LOG);
- p->skype = 0;
- p->skype_thread = AST_PTHREADT_NULL;
- if (option_debug > 100) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return -1;
- }
- }
-#else /* __CYGWIN__ */
-#ifdef WANT_SKYPE_X11
- struct AsteriskHandles *AsteriskHandlesAst;
+ if (func) {
+ if (http) {
+ stream->write_function(stream, "<pre>");
+ }
+ status = func(&argv[lead], argc - lead, stream);
+ if (http) {
+ stream->write_function(stream, "\n\n</pre>");
+ }
+ } else {
+ stream->write_function(stream, "Unknown Command [%s]\n", argv[0]);
+ }
- if (option_debug > 100) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- }
- AsteriskHandlesAst = &p->AsteriskHandlesAst;
+ done:
- DEBUGA_SKYPE("SENDING: |||%s||||\n", SKYPIAX_P_LOG, msg_to_skype);
+ if (http) {
- if (!skypiax_skype_send_message(AsteriskHandlesAst, msg_to_skype)) {
- ERRORA
- ("Sending message failed - probably Skype crashed.\n\nPlease shutdown Skypiax (Asterisk), then restart Skype from the menu, then launch Skypiax and try again.\n",
- SKYPIAX_P_LOG);
- p->skype = 0;
- p->skype_thread = AST_PTHREADT_NULL;
- if (option_debug > 100) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return -1;
- }
-#endif /* WANT_SKYPE_X11 */
-#endif /* __CYGWIN__ */
+ stream->write_function(stream,
+ "<br><br><table align=center><tr><td><center><form method=post>\n"
+ "<input type=text name=wcmd size=40><br><br>\n"
+ "<input name=action type=submit value=\"call\"> "
+ "<input name=action type=submit value=\"hangup\"> "
+ "<input name=action type=submit value=\"list\"> "
+ "<input name=action type=submit value=\"switch\"> "
+ "<input name=action type=submit value=\"mute\"> "
+ "<input name=action type=submit value=\"unmute\"> "
+ "<input name=action type=submit value=\"answer\"> <br><br>"
+ "<table border=1>\n"
+ "<tr><td><input name=action type=submit value=\"1\"></td>"
+ "<td><input name=action type=submit value=\"2\"></td>"
+ "<td><input name=action type=submit value=\"3\"></td>\n"
+ "<td><input name=action type=submit value=\"A\"></td></tr>\n"
+ "<tr><td><input name=action type=submit value=\"4\"></td>"
+ "<td><input name=action type=submit value=\"5\"></td>"
+ "<td><input name=action type=submit value=\"6\"></td>\n"
+ "<td><input name=action type=submit value=\"B\"></td></tr>\n"
+ "<tr><td><input name=action type=submit value=\"7\"></td>"
+ "<td><input name=action type=submit value=\"8\"></td>"
+ "<td><input name=action type=submit value=\"9\"></td>\n"
+ "<td><input name=action type=submit value=\"C\"></td></tr>\n"
+ "<tr><td><input name=action type=submit value=\"*\"></td>"
+ "<td><input name=action type=submit value=\"0\"></td>"
+ "<td><input name=action type=submit value=\"#\"></td>\n"
+ "<td><input name=action type=submit value=\"D\"></td></tr>\n" "</table>" "</form><br></center></td></tr></table>\n");
+ }
- if (option_debug > 100) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return 0;
+ switch_safe_free(mycmd);
+
+ return status;
}
-#if defined( WANT_SKYPE_X11 ) || defined( __CYGWIN__ )
-int skypiax_skype_call(struct skypiax_pvt *p, char *idest, int timeout)
-{
- char rdest[80];
- if (option_debug > 10) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- }
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
+ */
+#endif /* MOD_ALSA */
- if (!p->skype) {
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return 0;
- }
- strncpy(rdest, idest, sizeof(rdest) - 1);
- if (option_debug)
- DEBUGA_SKYPE("Calling Skype, rdest is: %s\n", SKYPIAX_P_LOG, rdest);
- //skypiax_skype_write(p, "GET AGC");
- //usleep(10000);
- skypiax_skype_write(p, "SET AGC OFF");
- usleep(10000);
- //skypiax_skype_write(p, "GET AGC");
- //usleep(10000);
- //skypiax_skype_write(p, "GET AEC");
- //usleep(10000);
- skypiax_skype_write(p, "SET AEC OFF");
- usleep(10000);
- //skypiax_skype_write(p, "GET AEC");
- //usleep(300000);
+#define MOD_SKYPIAX
- char msg_to_skype[1024];
- sprintf(msg_to_skype, "CALL %s", rdest);
- if (skypiax_skype_write(p, msg_to_skype) < 0) {
+#ifdef MOD_SKYPIAX
+#include <switch.h>
- ERRORA("failed to communicate with Skype client, now exit\n", SKYPIAX_P_LOG);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return -1;
- }
- //p->skype_call_ongoing = 1;
+SWITCH_MODULE_LOAD_FUNCTION(mod_skypiax_load);
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_skypiax_shutdown);
+//SWITCH_MODULE_RUNTIME_FUNCTION(mod_skypiax_runtime);
+SWITCH_MODULE_DEFINITION(mod_skypiax, mod_skypiax_load, mod_skypiax_shutdown, NULL); //mod_skypiax_runtime);
- //if (p->owner) {
- //ast_setstate(p->owner, AST_STATE_RINGING);
- //}
- ast_queue_control(p->owner, AST_CONTROL_RINGING);
- return 0;
-}
-#if 0
-void skypiax_skype_disconnect(void)
-{
- struct skypiax_pvt *p = NULL;
+switch_endpoint_interface_t *skypiax_endpoint_interface;
+static switch_memory_pool_t *module_pool = NULL;
+static int running = 1;
- if (option_debug > 10) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- }
- if (!ast_mutex_lock(&skypiax_iflock)) {
- /* Hangup all interfaces if they have an owner */
- p = skypiax_iflist;
- while (p) {
- if (p->skype_thread != AST_PTHREADT_NULL) {
+typedef enum {
+ TFLAG_IO = (1 << 0),
+ TFLAG_INBOUND = (1 << 1),
+ TFLAG_OUTBOUND = (1 << 2),
+ TFLAG_DTMF = (1 << 3),
+ TFLAG_VOICE = (1 << 4),
+ TFLAG_HANGUP = (1 << 5),
+ TFLAG_LINEAR = (1 << 6),
+ TFLAG_CODEC = (1 << 7),
+ TFLAG_BREAK = (1 << 8)
+} TFLAGS;
- if (!p->skype) {
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return;
- }
+typedef enum {
+ GFLAG_MY_CODEC_PREFS = (1 << 0)
+} GFLAGS;
- DEBUGA_SKYPE("disconnecting skypiax module from skype\n", SKYPIAX_P_LOG);
-#ifdef __CYGWIN__
- char msg_to_skype[1024];
- sprintf(msg_to_skype, "#disconnect");
- skypiax_skype_write(p, msg_to_skype);
-#endif /* __CYGWIN__ */
- p->skype_call_id[0] = '\0';
- p->skype_call_id[0] = '\0';
- p->skype_call_ongoing = 0;
- DEBUGA_SKYPE("TO BE killed skype_thread=%lu STOP=%lu NULL=%lu\n", SKYPIAX_P_LOG,
- (unsigned long) p->skype_thread, (unsigned long) AST_PTHREADT_STOP,
- (unsigned long) AST_PTHREADT_NULL);
-#ifdef __CYGWIN__
- PostMessage(p->AsteriskHandlesAst.win32_hInit_MainWindowHandle, WM_CLOSE, 0, 0);
- p->skype_thread = AST_PTHREADT_NULL;
-#else /* __CYGWIN__ */
- pthread_cancel(p->skype_thread);
- /* Nudge it a little, as it's probably stuck in select */
- pthread_kill(p->skype_thread, SIGURG);
- p->skype_thread = AST_PTHREADT_NULL;
-#endif /* __CYGWIN__ */
- DEBUGA_SKYPE("KILLED skype_thread=%lu STOP=%lu NULL=%lu\n", SKYPIAX_P_LOG,
- (unsigned long) p->skype_thread, (unsigned long) AST_PTHREADT_STOP,
- (unsigned long) AST_PTHREADT_NULL);
- }
- p = p->next;
- }
- ast_mutex_unlock(&skypiax_iflock);
- } else {
- ERRORA("Unable to lock the interface\n", SKYPIAX_P_LOG);
- }
- DEBUGA_SKYPE("disconnected skypiax module from skype\n", SKYPIAX_P_LOG);
- usleep(500);
-#ifdef WANT_SKYPE_X11
- //system("killall -9 skype; sleep 1");
-#endif /* WANT_SKYPE_X11 */
-}
-#endif
-#endif /* defined( WANT_SKYPE_X11 ) || defined( __CYGWIN__ ) */
+static struct {
+ int debug;
+ char *ip;
+ int port;
+ char *dialplan;
+ char *codec_string;
+ char *codec_order[SWITCH_MAX_CODECS];
+ int codec_order_last;
+ char *codec_rates_string;
+ char *codec_rates[SWITCH_MAX_CODECS];
+ int codec_rates_last;
+ unsigned int flags;
+ int calls;
+ switch_mutex_t *mutex;
+} globals;
-#define SAMPLES_PER_FRAME 160
-int skypiax_skypeaudio_init(struct skypiax_pvt *p)
-{
- int c;
-/* build the pipe that will be polled on by pbx */
- c = pipe(p->audiopipe);
- if (c) {
- ERRORA("Unable to create audio pipe\n", SKYPIAX_P_LOG);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return -1;
- }
+struct private_object {
+ unsigned int flags;
+ switch_codec_t read_codec;
+ switch_codec_t write_codec;
+ switch_frame_t read_frame;
+ unsigned char databuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
+ switch_core_session_t *session;
+ switch_caller_profile_t *caller_profile;
+ switch_mutex_t *mutex;
+ switch_mutex_t *flag_mutex;
+ //switch_thread_cond_t *cond;
+};
-/* the pipe is our audio fd for pbx to poll on */
- p->skypiax_sound_capt_fd = p->audiopipe[0];
+typedef struct private_object private_t;
- /* let's start the serial monitoring thread too, so we can have serial signaling */
- if (ast_pthread_create(&p->tcp_srv_thread, NULL, skypiax_do_tcp_srv_thread, p) < 0) {
- ERRORA("Unable to start tcp_srv_thread thread.\n", SKYPIAX_P_LOG);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return -1;
- }
- c = pipe(p->audioskypepipe);
- if (c) {
- ERRORA("Unable to create audioskypepipe\n", SKYPIAX_P_LOG);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return -1;
- }
- fcntl(p->audioskypepipe[0], F_SETFL, O_NONBLOCK);
- fcntl(p->audioskypepipe[1], F_SETFL, O_NONBLOCK);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_codec_string, globals.codec_string);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_codec_rates_string, globals.codec_rates_string);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_ip, globals.ip);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return 0;
-}
-struct ast_frame *skypiax_skypeaudio_read(struct skypiax_pvt *p)
-{
- static struct ast_frame f;
- static short __buf[SKYPIAX_FRAME_SIZE + AST_FRIENDLY_OFFSET / 2];
- short *buf;
- int samples;
- if (option_debug > 100) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- }
- memset(__buf, '\0', (SKYPIAX_FRAME_SIZE + AST_FRIENDLY_OFFSET / 2));
- buf = __buf + AST_FRIENDLY_OFFSET / 2;
+static switch_status_t channel_on_init(switch_core_session_t *session);
+static switch_status_t channel_on_hangup(switch_core_session_t *session);
+static switch_status_t channel_on_routing(switch_core_session_t *session);
+static switch_status_t channel_on_exchange_media(switch_core_session_t *session);
+static switch_status_t channel_on_soft_execute(switch_core_session_t *session);
+static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event,
+ switch_caller_profile_t *outbound_profile,
+ switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags);
+static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id);
+static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
+static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig);
- f.frametype = AST_FRAME_NULL;
- f.subclass = 0;
- f.samples = 0;
- f.datalen = 0;
- f.data = NULL;
- f.offset = 0;
- f.src = skypiax_type;
- f.mallocd = 0;
- f.delivery.tv_sec = 0;
- f.delivery.tv_usec = 0;
- if ((samples = read(p->audiopipe[0], buf, SAMPLES_PER_FRAME * sizeof(short))) != 320) {
- DEBUGA_SOUND("read=====> NOT GOOD samples=%d expected=%d\n", SKYPIAX_P_LOG, samples,
- SAMPLES_PER_FRAME * sizeof(short));
- usleep(100);
- //do nothing
- } else {
- //DEBUGA_SOUND("read=====> GOOD samples=%d\n", SKYPIAX_P_LOG, samples);
- /* A real frame */
- f.frametype = AST_FRAME_VOICE;
- f.subclass = AST_FORMAT_SLINEAR;
- f.samples = SKYPIAX_FRAME_SIZE;
- f.datalen = SKYPIAX_FRAME_SIZE * 2;
- f.data = buf;
- f.offset = AST_FRIENDLY_OFFSET;
- f.src = skypiax_type;
- f.mallocd = 0;
- }
- if (option_debug > 100) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return &f;
+static void tech_init(private_t *tech_pvt, switch_core_session_t *session)
+{
+ tech_pvt->read_frame.data = tech_pvt->databuf;
+ tech_pvt->read_frame.buflen = sizeof(tech_pvt->databuf);
+ switch_mutex_init(&tech_pvt->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
+ switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
+ switch_core_session_set_private(session, tech_pvt);
+ tech_pvt->session = session;
}
-#define NN 160
-#define GG 160
-void *skypiax_do_tcp_srv_thread(void *data)
+/*
+ State methods they get called when the state changes to the specific state
+ returning SWITCH_STATUS_SUCCESS tells the core to execute the standard state method next
+ so if you fully implement the state you can return SWITCH_STATUS_FALSE to skip it.
+*/
+static switch_status_t channel_on_init(switch_core_session_t *session)
{
- struct skypiax_pvt *p = data;
- short in[GG];
- short out[GG / 2];
- int s, fd, len, sent;
- unsigned int sin_size;
- struct sockaddr_in my_addr;
- struct sockaddr_in remote_addr;
- int exit = 0;
- int a;
- int i;
+ switch_channel_t *channel;
+ private_t *tech_pvt = NULL;
- if (option_debug > 10) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- }
- memset(&my_addr, 0, sizeof(my_addr));
- my_addr.sin_family = AF_INET;
- my_addr.sin_addr.s_addr = INADDR_ANY;
- my_addr.sin_port = htons(5556);
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
- if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- ERRORA("socket Error\n", SKYPIAX_P_LOG);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return NULL;
- }
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+ switch_set_flag_locked(tech_pvt, TFLAG_IO);
- if (bind(s, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) < 0) {
- ERRORA("bind Error\n", SKYPIAX_P_LOG);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return NULL;
- }
- DEBUGA_SKYPE("started tcp_srv_thread thread.\n", SKYPIAX_P_LOG);
+ /* Move channel's state machine to ROUTING. This means the call is trying
+ to get from the initial start where the call because, to the point
+ where a destination has been identified. If the channel is simply
+ left in the initial state, nothing will happen. */
+ switch_channel_set_state(channel, CS_ROUTING);
+ switch_mutex_lock(globals.mutex);
+ globals.calls++;
+ switch_mutex_unlock(globals.mutex);
- listen(s, 6);
+ return SWITCH_STATUS_SUCCESS;
+}
- sin_size = sizeof(remote_addr);
- while ((fd = accept(s, (struct sockaddr *) &remote_addr, &sin_size)) > 0) {
- while (1) {
- len = recv(fd, in, sizeof(short) * GG, 0);
- if (len > 0) {
- a = 0;
- for (i = 0; i < len / sizeof(short); i++) {
- out[a] = in[i];
- i++;
- a++;
- }
+static switch_status_t channel_on_routing(switch_core_session_t *session)
+{
+ switch_channel_t *channel = NULL;
+ private_t *tech_pvt = NULL;
- if (!p->audiobuf_is_loaded) {
- for (i = 0; i < (len / sizeof(short)) / 2; i++) {
- p->audiobuf[i] = out[i];
- }
- p->audiobuf_is_loaded = 1;
- } else {
- sent = write(p->audiopipe[1], p->audiobuf, len / 2);
- sent = write(p->audiopipe[1], out, len / 2);
- p->audiobuf_is_loaded = 0;
- //DEBUGA_SOUND("read=====> req=%d recv=%d to sent=%d sent=%d\n", SKYPIAX_P_LOG, sizeof(short)*GG, len, (len*sizeof(short))/2, sent);
- }
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
- } else if (len == 0) {
- DEBUGA_SKYPE("client GONE\n", SKYPIAX_P_LOG);
- break;
- } else {
- ERRORA("len=%d\n", SKYPIAX_P_LOG, len);
- exit = 1;
- break;
- }
- }
- DEBUGA_SKYPE("client GONE\n", SKYPIAX_P_LOG);
- close(fd);
- if (exit)
- break;
- }
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
- DEBUGA_SKYPE("server (I am it) GONE\n", SKYPIAX_P_LOG);
- close(s);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return NULL;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL ROUTING\n", switch_channel_get_name(channel));
+
+ return SWITCH_STATUS_SUCCESS;
}
-void *skypiax_do_tcp_cli_thread(void *data)
+
+static switch_status_t channel_on_execute(switch_core_session_t *session)
{
- struct skypiax_pvt *p = data;
- int s, fd, len;
- short in[NN / 2];
- short out[NN];
- unsigned int sin_size;
- struct sockaddr_in my_addr;
- struct sockaddr_in remote_addr;
- int a;
- int i;
- int got;
- if (option_debug > 10) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- }
- memset(&my_addr, 0, sizeof(my_addr));
- my_addr.sin_family = AF_INET;
- my_addr.sin_addr.s_addr = INADDR_ANY;
- my_addr.sin_port = htons(5558);
+ switch_channel_t *channel = NULL;
+ private_t *tech_pvt = NULL;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL EXECUTE\n", switch_channel_get_name(channel));
- if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- ERRORA("socket Error\n", SKYPIAX_P_LOG);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return NULL;
- }
- if (bind(s, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) < 0) {
- ERRORA("bind Error\n", SKYPIAX_P_LOG);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return NULL;
- }
- DEBUGA_SKYPE("started tcp_cli_thread thread.\n", SKYPIAX_P_LOG);
+ return SWITCH_STATUS_SUCCESS;
+}
- listen(s, 6);
+static switch_status_t channel_on_hangup(switch_core_session_t *session)
+{
+ switch_channel_t *channel = NULL;
+ private_t *tech_pvt = NULL;
- sin_size = sizeof(remote_addr);
- while ((fd = accept(s, (struct sockaddr *) &remote_addr, &sin_size)) > 0) {
- DEBUGA_SKYPE("ACCEPTED\n", SKYPIAX_P_LOG);
- while (1 && p->owner && p->owner->_state == AST_STATE_UP) {
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
- got = read(p->audioskypepipe[0], in, (NN / 2) * sizeof(short));
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
- if (got > 0) {
- a = 0;
- for (i = 0; i < got / sizeof(short); i++) {
- out[a] = in[i];
- a++;
- out[a] = in[i];
- a++;
- }
+ switch_clear_flag_locked(tech_pvt, TFLAG_IO);
+ switch_clear_flag_locked(tech_pvt, TFLAG_VOICE);
+ //switch_thread_cond_signal(tech_pvt->cond);
- len = send(fd, out, got * 2, 0);
+ if (tech_pvt->read_codec.implementation) {
+ switch_core_codec_destroy(&tech_pvt->read_codec);
+ }
- if (len == 0) {
- DEBUGA_SKYPE("client GONE\n", SKYPIAX_P_LOG);
- break;
- }
- } else {
- usleep(100);
- }
+ if (tech_pvt->write_codec.implementation) {
+ switch_core_codec_destroy(&tech_pvt->write_codec);
+ }
- }
- DEBUGA_SKYPE("client GONE\n", SKYPIAX_P_LOG);
- close(fd);
- }
- DEBUGA_SKYPE("server (I am it) GONE\n", SKYPIAX_P_LOG);
- close(s);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return NULL;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL HANGUP\n", switch_channel_get_name(channel));
+ switch_mutex_lock(globals.mutex);
+ globals.calls--;
+ if (globals.calls < 0) {
+ globals.calls = 0;
+ }
+ switch_mutex_unlock(globals.mutex);
+
+ return SWITCH_STATUS_SUCCESS;
}
-int skypiax_skypeaudio_write(struct skypiax_pvt *p, struct ast_frame *f)
+static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig)
{
- int sent;
+ switch_channel_t *channel = NULL;
+ private_t *tech_pvt = NULL;
- if (option_debug > 100) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- }
- sent = write(p->audioskypepipe[1], (short *) f->data, f->datalen);
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
- if (option_debug > 100) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return 0;
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ switch (sig) {
+ case SWITCH_SIG_KILL:
+ switch_clear_flag_locked(tech_pvt, TFLAG_IO);
+ switch_clear_flag_locked(tech_pvt, TFLAG_VOICE);
+ switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
+ //switch_thread_cond_signal(tech_pvt->cond);
+ break;
+ case SWITCH_SIG_BREAK:
+ switch_set_flag_locked(tech_pvt, TFLAG_BREAK);
+ break;
+ default:
+ break;
+ }
+
+ return SWITCH_STATUS_SUCCESS;
}
-int skypiax_console_skype(int fd, int argc, char *argv[])
+
+static switch_status_t channel_on_exchange_media(switch_core_session_t *session)
{
- struct skypiax_pvt *p = skypiax_console_find_desc(skypiax_console_active);
- char skype_msg[1024];
- int i, a, c;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CHANNEL LOOPBACK\n");
+ return SWITCH_STATUS_SUCCESS;
+}
- if (argc == 1) {
- return RESULT_SHOWUSAGE;
- }
- if (!p) {
- ast_cli(fd,
- "No \"current\" console for skypiax_skype, please enter 'help console'\n");
- return RESULT_SUCCESS;
- }
- if (option_debug > 10) {
- DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
- }
- if (!p->skype) {
- ast_cli(fd, "The \"current\" console is not connected to a Skype client'\n");
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return RESULT_SUCCESS;
- }
+static switch_status_t channel_on_soft_execute(switch_core_session_t *session)
+{
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CHANNEL TRANSMIT\n");
+ return SWITCH_STATUS_SUCCESS;
+}
- memset(skype_msg, 0, sizeof(skype_msg));
- c = 0;
- for (i = 1; i < argc; i++) {
- for (a = 0; a < strlen(argv[i]); a++) {
- skype_msg[c] = argv[i][a];
- c++;
- if (c == 1022)
- break;
- }
- if (i != argc - 1) {
- skype_msg[c] = ' ';
- c++;
- }
- if (c == 1023)
- break;
- }
- skypiax_skype_write(p, skype_msg);
- if (option_debug > 10) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return RESULT_SUCCESS;
+static switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)
+{
+ private_t *tech_pvt = switch_core_session_get_private(session);
+ switch_assert(tech_pvt != NULL);
+
+ return SWITCH_STATUS_SUCCESS;
}
-/* For simplicity, I'm keeping the format compatible with the voicemail config,
- but i'm open to suggestions for isolating it */
+static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
+{
+ switch_channel_t *channel = NULL;
+ private_t *tech_pvt = NULL;
+ //switch_time_t started = switch_time_now();
+ //unsigned int elapsed;
+ switch_byte_t *data;
-#define SKYPIAX_DIR_CONFIG "directoriax.conf"
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
-int skypiax_console_skypiax_dir_import(int fd, int argc, char *argv[])
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+ tech_pvt->read_frame.flags = SFF_NONE;
+ *frame = NULL;
+
+ while (switch_test_flag(tech_pvt, TFLAG_IO)) {
+
+ if (switch_test_flag(tech_pvt, TFLAG_BREAK)) {
+ switch_clear_flag(tech_pvt, TFLAG_BREAK);
+ goto cng;
+ }
+
+ if (!switch_test_flag(tech_pvt, TFLAG_IO)) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (switch_test_flag(tech_pvt, TFLAG_IO) && switch_test_flag(tech_pvt, TFLAG_VOICE)) {
+ switch_clear_flag_locked(tech_pvt, TFLAG_VOICE);
+ if (!tech_pvt->read_frame.datalen) {
+ continue;
+ }
+ *frame = &tech_pvt->read_frame;
+#ifdef BIGENDIAN
+ if (switch_test_flag(tech_pvt, TFLAG_LINEAR)) {
+ switch_swap_linear((*frame)->data, (int) (*frame)->datalen / 2);
+ }
+#endif
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ switch_yield(1000);
+ }
+
+
+ return SWITCH_STATUS_FALSE;
+
+ cng:
+ data = (switch_byte_t *) tech_pvt->read_frame.data;
+ data[0] = 65;
+ data[1] = 0;
+ tech_pvt->read_frame.datalen = 2;
+ tech_pvt->read_frame.flags = SFF_CNG;
+ *frame = &tech_pvt->read_frame;
+ return SWITCH_STATUS_SUCCESS;
+
+}
+
+static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
{
- //int res;
- struct skypiax_pvt *p = skypiax_console_find_desc(skypiax_console_active);
- //char list_command[64];
- char fn[256];
- char date[256] = "";
- time_t t;
- char *configfile = SKYPIAX_DIR_CONFIG;
- int add_to_skypiax_dir_conf = 1;
- //int fromskype = 0;
- //int fromcell = 0;
+ switch_channel_t *channel = NULL;
+ private_t *tech_pvt = NULL;
+ //switch_frame_t *pframe;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
-#if 0
- if(directoriax_entry_extension){
- skypiax_dir_entry_extension=directoriax_entry_extension;
- }else{
- ast_cli(fd, "No 'directoriax_entry_extension', you MUST have loaded directoriax.so\n");
- return RESULT_SUCCESS;
- }
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ if (!switch_test_flag(tech_pvt, TFLAG_IO)) {
+ return SWITCH_STATUS_FALSE;
+ }
+#ifdef BIGENDIAN
+ if (switch_test_flag(tech_pvt, TFLAG_LINEAR)) {
+ switch_swap_linear(frame->data, (int) frame->datalen / 2);
+ }
#endif
- if (argc != 2)
- return RESULT_SHOWUSAGE;
- if (!p) {
- ast_cli(fd, "No \"current\" console ???, please enter 'help skypiax_console'\n");
- return RESULT_SUCCESS;
- }
- if (!strcasecmp(argv[1], "add"))
- add_to_skypiax_dir_conf = 1;
- else if (!strcasecmp(argv[1], "replace"))
- add_to_skypiax_dir_conf = 0;
- else {
- ast_cli(fd, "\n\nYou have neither specified 'add' nor 'replace'\n\n");
- return RESULT_SHOWUSAGE;
- }
+ return SWITCH_STATUS_SUCCESS;
-#if 0
- if (!strcasecmp(argv[2], "fromskype"))
- fromskype = 1;
- else if (!strcasecmp(argv[2], "fromcell"))
- fromcell = 1;
- else {
- ast_cli(fd, "\n\nYou have neither specified 'fromskype' nor 'fromcell'\n\n");
- return RESULT_SHOWUSAGE;
- }
+}
- if (fromcell) {
- ast_cli(fd,
- "Importing from cellphone is currently supported only on \"AT\" cellphones :( !\n");
- //fclose(p->phonebook_writing_fp);
- //skypiax_dir_create_extensions();
- return RESULT_SUCCESS;
- }
+static switch_status_t channel_answer_channel(switch_core_session_t *session)
+{
+ private_t *tech_pvt;
+ switch_channel_t *channel = NULL;
- if (fromskype)
- if (!p->skype) {
- ast_cli(fd, "Importing from skype is supported by skypiax_dir on chan_skypiax!\n");
- //fclose(p->phonebook_writing_fp);
- //skypiax_dir_create_extensions();
- return RESULT_SUCCESS;
- }
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
- if (fromcell || fromskype)
- if (argc != 3) {
- ast_cli(fd,
- "\n\nYou don't have to specify a filename with 'fromcell' or with 'fromskype'\n\n");
- return RESULT_SHOWUSAGE;
- }
-#endif
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
- /*******************************************************************************************/
- if (configfile[0] == '/') {
- ast_copy_string(fn, configfile, sizeof(fn));
- } else {
- snprintf(fn, sizeof(fn), "%s/%s", ast_config_AST_CONFIG_DIR, configfile);
- }
- if (option_debug)
- NOTICA("Opening '%s'\n", SKYPIAX_P_LOG, fn);
- time(&t);
- ast_copy_string(date, ctime(&t), sizeof(date));
+ return SWITCH_STATUS_SUCCESS;
+}
- if (add_to_skypiax_dir_conf)
- p->phonebook_writing_fp = fopen(fn, "a+");
- else
- p->phonebook_writing_fp = fopen(fn, "w+");
- if (p->phonebook_writing_fp) {
- if (add_to_skypiax_dir_conf) {
- if (option_debug)
- NOTICA("Opened '%s' for appending \n", SKYPIAX_P_LOG, fn);
- fprintf(p->phonebook_writing_fp, ";!\n");
- fprintf(p->phonebook_writing_fp, ";! Update Date: %s", date);
- fprintf(p->phonebook_writing_fp, ";! Updated by: %s, %d\n", __FILE__, __LINE__);
- fprintf(p->phonebook_writing_fp, ";!\n");
- } else {
- if (option_debug)
- NOTICA("Opened '%s' for writing \n", SKYPIAX_P_LOG, fn);
- fprintf(p->phonebook_writing_fp, ";!\n");
- fprintf(p->phonebook_writing_fp, ";! Automatically generated configuration file\n");
- fprintf(p->phonebook_writing_fp, ";! Filename: %s (%s)\n", configfile, fn);
- fprintf(p->phonebook_writing_fp, ";! Creation Date: %s", date);
- fprintf(p->phonebook_writing_fp, ";! Generated by: %s, %d\n", __FILE__, __LINE__);
- fprintf(p->phonebook_writing_fp, ";!\n");
- fprintf(p->phonebook_writing_fp, "[general]\n\n");
- fprintf(p->phonebook_writing_fp, "[default]\n");
- }
+static switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg)
+{
+ switch_channel_t *channel;
+ private_t *tech_pvt;
- /*******************************************************************************************/
- //if (fromskype) {
- if (p->skype) {
- WARNINGA
- ("About to querying the Skype client 'Contacts', it may take some moments... Don't worry.\n",
- SKYPIAX_P_LOG);
- if (p->skype_thread != AST_PTHREADT_NULL) {
- char msg_to_skype[1024];
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
- p->skype_friends[0] = '\0';
- sprintf(msg_to_skype, "#333 SEARCH FRIENDS");
- if (skypiax_skype_write(p, msg_to_skype) < 0) {
- return -1;
- }
+ tech_pvt = (private_t *) switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
- int friends_count = 0;
- while (p->skype_friends[0] == '\0') {
- /* FIXME needs a timeout, can't wait forever!
- * eg. when skype is running but not connected! */
- usleep(100);
- friends_count++;
- if (friends_count > 20000) {
- return -1; /* FIXME */
- }
- }
+ switch (msg->message_id) {
+ case SWITCH_MESSAGE_INDICATE_ANSWER:
+ {
+ channel_answer_channel(session);
+ }
+ break;
+ default:
+ break;
+ }
- }
+ return SWITCH_STATUS_SUCCESS;
+}
- if (p->skype_thread != AST_PTHREADT_NULL) {
- char msg_to_skype[1024];
+/* Make sure when you have 2 sessions in the same scope that you pass the appropriate one to the routines
+ that allocate memory or you will have 1 channel with memory allocated from another channel's pool!
+*/
+static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event,
+ switch_caller_profile_t *outbound_profile,
+ switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags)
+{
+ if ((*new_session = switch_core_session_request(skypiax_endpoint_interface, pool)) != 0) {
+ private_t *tech_pvt;
+ switch_channel_t *channel;
+ switch_caller_profile_t *caller_profile;
- if (p->skype_friends[0] != '\0') {
- char *buf, *where;
- char **stringp;
- int skype_dir_file_written = 0;
+ switch_core_session_add_stream(*new_session, NULL);
+ if ((tech_pvt = (private_t *) switch_core_session_alloc(*new_session, sizeof(private_t))) != 0) {
+ channel = switch_core_session_get_channel(*new_session);
+ tech_init(tech_pvt, *new_session);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Hey where is my memory pool?\n");
+ switch_core_session_destroy(new_session);
+ return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+ }
- buf = p->skype_friends;
- stringp = &buf;
- where = strsep(stringp, ", ");
- while (where) {
- if (where[0] != '\0') {
- /*
- * So, we have the Skype username (the HANDLE, I think is called).
- * But we want to call the names we see in the Skype contact list
- * So, let's check the DISPLAYNAME (the end user modified contact name)
- * Then, we check the FULLNAME (that appears as it was the DISPLAYNAME
- * if the end user has not modify it)
- * If we still have neither DISPLAYNAME nor FULLNAME, we'll use the
- * Skipe username (the HANDLE)
- */
+ if (outbound_profile) {
+ char name[128];
- p->skype_displayname[0] = '\0';
- sprintf(msg_to_skype, "#765 GET USER %s DISPLAYNAME", where);
- skypiax_skype_write(p, msg_to_skype);
- int displayname_count = 0;
- while (p->skype_displayname[0] == '\0') {
- /* FIXME needs a timeout, can't wait forever!
- * eg. when skype is running but not connected! */
- usleep(100);
- displayname_count++;
- if (displayname_count > 20000)
- return -1; /* FIXME */
- }
- if (p->skype_displayname[0] != '\0') {
- char *where2;
- char sanitized[300];
+ snprintf(name, sizeof(name), "SKYPIAX/%s", outbound_profile->destination_number);
+ switch_channel_set_name(channel, name);
- sanitized[0] = '\0';
+ caller_profile = switch_caller_profile_clone(*new_session, outbound_profile);
+ switch_channel_set_caller_profile(channel, caller_profile);
+ tech_pvt->caller_profile = caller_profile;
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Doh! no caller profile\n");
+ switch_core_session_destroy(new_session);
+ return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+ }
- where2 = strstr(p->skype_displayname, "DISPLAYNAME ");
- if (where2) {
- /* there can be some *smart* that makes a displayname
- * that is different than first<space>last, */
- /* maybe initials, simbols, slashes,
- * something smartish... let's check */
- if (where2[12] != '\0') {
- int i = 12;
- int x = 0;
- int spaces = 0;
- int last_char_was_space = 0;
+ switch_channel_set_flag(channel, CF_OUTBOUND);
+ switch_set_flag_locked(tech_pvt, TFLAG_OUTBOUND);
+ switch_channel_set_state(channel, CS_INIT);
+ return SWITCH_CAUSE_SUCCESS;
+ }
- for (i = 12; i < strlen(where2) && x < 299; i++) {
- if (!isalnum(where2[i])) {
- if (!isblank(where2[i])) {
- /* bad char */
- continue;
- }
- /* is a space */
- if (last_char_was_space == 1) /* do not write 2 consecutive spaces */
- continue;
- last_char_was_space = 1;
- sanitized[x] = ' ';
- x++;
- continue;
- }
- /* is alphanum */
- last_char_was_space = 0;
- sanitized[x] = where2[i];
- x++;
- continue;
- }
+ return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
- sanitized[x] = '\0';
- if (spaces == 0) {
- }
- DEBUGA_SKYPE("sanitized=|%s|, where=|%s|, where2=|%s|\n",
- SKYPIAX_P_LOG, sanitized, where, &where2[12]);
- }
+}
- if (where2[12] != '\0') {
- skypiax_dir_entry_extension++;
- if (where[0] == '+' || isdigit(where[0])) { /* is a skypeout number */
- fprintf(p->phonebook_writing_fp,
- "%s => ,%sSKO,,,hidefromdir=%s|phonebook_direct_calling_ext=%d%s%.4d|phonebook_entry_fromskype=%s|phonebook_entry_owner=%s\n",
- where, sanitized, "no",
- p->skypiax_dir_entry_extension_prefix, "2",
- skypiax_dir_entry_extension, "yes", "not_specified");
- } else { /* is a skype name */
- fprintf(p->phonebook_writing_fp,
- "%s => ,%sSKY,,,hidefromdir=%s|phonebook_direct_calling_ext=%d%s%.4d|phonebook_entry_fromskype=%s|phonebook_entry_owner=%s\n",
- where, sanitized, "no",
- p->skypiax_dir_entry_extension_prefix, "1",
- skypiax_dir_entry_extension, "yes", "not_specified");
- }
- skype_dir_file_written = 1;
+static switch_status_t channel_receive_event(switch_core_session_t *session, switch_event_t *event)
+{
+ struct private_object *tech_pvt = switch_core_session_get_private(session);
+ char *body = switch_event_get_body(event);
+ switch_assert(tech_pvt != NULL);
- }
- }
- }
- p->skype_displayname[0] = '\0';
+ if (!body) {
+ body = "";
+ }
- p->skype_fullname[0] = '\0';
- sprintf(msg_to_skype, "#222 GET USER %s FULLNAME", where);
- skypiax_skype_write(p, msg_to_skype);
- int fullname_count = 0;
- while (p->skype_fullname[0] == '\0') {
- /* FIXME needs a timeout, can't wait forever!
- * eg. when skype is running but not connected! */
- usleep(100);
- fullname_count++;
- if (fullname_count > 20000)
- return -1; /* FIXME */
- }
- if (p->skype_fullname[0] != '\0') {
- char *where2;
- char sanitized[300];
+ return SWITCH_STATUS_SUCCESS;
+}
- where2 = strstr(p->skype_fullname, "FULLNAME ");
- if (where2) {
- /* there can be some *smart* that makes a fullname
- * that is different than first<space>last, */
- /* maybe initials, simbols, slashes,
- * something smartish... let's check */
- if (where2[9] != '\0') {
- int i = 9;
- int x = 0;
- int spaces = 0;
- int last_char_was_space = 0;
+switch_state_handler_table_t skypiax_state_handlers = {
+ /*.on_init */ channel_on_init,
+ /*.on_routing */ channel_on_routing,
+ /*.on_execute */ channel_on_execute,
+ /*.on_hangup */ channel_on_hangup,
+ /*.on_exchange_media */ channel_on_exchange_media,
+ /*.on_soft_execute */ channel_on_soft_execute
+};
- for (i = 9; i < strlen(where2) && x < 299; i++) {
- if (!isalnum(where2[i])) {
- if (!isblank(where2[i])) {
- /* bad char */
- continue;
- }
- /* is a space */
- if (last_char_was_space == 1) /* do not write 2 consecutive spaces */
- continue;
- last_char_was_space = 1;
- sanitized[x] = ' ';
- x++;
- continue;
- }
- /* alphanum */
- last_char_was_space = 0;
- sanitized[x] = where2[i];
- x++;
- continue;
- }
+switch_io_routines_t skypiax_io_routines = {
+ /*.outgoing_channel */ channel_outgoing_channel,
+ /*.read_frame */ channel_read_frame,
+ /*.write_frame */ channel_write_frame,
+ /*.kill_channel */ channel_kill_channel,
+ /*.send_dtmf */ channel_send_dtmf,
+ /*.receive_message */ channel_receive_message,
+ /*.receive_event */ channel_receive_event
+};
- sanitized[x] = '\0';
- if (spaces == 0) {
- }
- DEBUGA_SKYPE("sanitized=|%s|, where=|%s|, where2=|%s|\n",
- SKYPIAX_P_LOG, sanitized, where, &where2[9]);
- }
+static switch_status_t load_config(void)
+{
+ char *cf = "skypiax.conf";
+ switch_xml_t cfg, xml, settings, param;
- if (skype_dir_file_written == 0) {
- skypiax_dir_entry_extension++;
- if (where2[9] != '\0') {
- if (where[0] == '+' || isdigit(where[0])) { /* is a skypeout number */
- fprintf(p->phonebook_writing_fp,
- "%s => ,%sSKO,,,hidefromdir=%s|phonebook_direct_calling_ext=%d%s%.4d|phonebook_entry_fromskype=%s|phonebook_entry_owner=%s\n",
- where, sanitized, "no",
- p->skypiax_dir_entry_extension_prefix, "2",
- skypiax_dir_entry_extension, "yes", "not_specified");
- } else { /* is a skype name */
- fprintf(p->phonebook_writing_fp,
- "%s => ,%sSKY,,,hidefromdir=%s|phonebook_direct_calling_ext=%d%s%.4d|phonebook_entry_fromskype=%s|phonebook_entry_owner=%s\n",
- where, sanitized, "no",
- p->skypiax_dir_entry_extension_prefix, "1",
- skypiax_dir_entry_extension, "yes", "not_specified");
+ memset(&globals, 0, sizeof(globals));
+ switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, module_pool);
+ if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", cf);
+ return SWITCH_STATUS_TERM;
+ }
- }
+ if ((settings = switch_xml_child(cfg, "settings"))) {
+ for (param = switch_xml_child(settings, "param"); param; param = param->next) {
+ char *var = (char *) switch_xml_attr_soft(param, "name");
+ char *val = (char *) switch_xml_attr_soft(param, "value");
- } else {
- if (where[0] == '+' || isdigit(where[0])) { /* is a skypeout number */
- fprintf(p->phonebook_writing_fp,
- "%s => ,%sSKO,,,hidefromdir=%s|phonebook_direct_calling_ext=%d%s%.4d|phonebook_entry_fromskype=%s|phonebook_entry_owner=%s\n",
- where, where, "no",
- p->skypiax_dir_entry_extension_prefix, "2",
- skypiax_dir_entry_extension, "yes", "not_specified");
- } else { /* is a skype name */
- fprintf(p->phonebook_writing_fp,
- "%s => ,%sSKY,,,hidefromdir=%s|phonebook_direct_calling_ext=%d%s%.4d|phonebook_entry_fromskype=%s|phonebook_entry_owner=%s\n",
- where, where, "no",
- p->skypiax_dir_entry_extension_prefix, "1",
- skypiax_dir_entry_extension, "yes", "not_specified");
+ if (!strcmp(var, "debug")) {
+ globals.debug = atoi(val);
+ } else if (!strcmp(var, "port")) {
+ globals.port = atoi(val);
+ } else if (!strcmp(var, "ip")) {
+ set_global_ip(val);
+ } else if (!strcmp(var, "codec-master")) {
+ if (!strcasecmp(val, "us")) {
+ switch_set_flag(&globals, GFLAG_MY_CODEC_PREFS);
+ }
+ } else if (!strcmp(var, "dialplan")) {
+ set_global_dialplan(val);
+ } else if (!strcmp(var, "codec-prefs")) {
+ set_global_codec_string(val);
+ globals.codec_order_last = switch_separate_string(globals.codec_string, ',', globals.codec_order, SWITCH_MAX_CODECS);
+ } else if (!strcmp(var, "codec-rates")) {
+ set_global_codec_rates_string(val);
+ globals.codec_rates_last = switch_separate_string(globals.codec_rates_string, ',', globals.codec_rates, SWITCH_MAX_CODECS);
+ }
+ }
+ }
- }
- }
- }
+ if (!globals.dialplan) {
+ set_global_dialplan("default");
+ }
- skype_dir_file_written = 0;
+ if (!globals.port) {
+ globals.port = 4569;
+ }
- }
+ switch_xml_free(xml);
- }
- p->skype_fullname[0] = '\0';
+ return SWITCH_STATUS_SUCCESS;
+}
- }
- where = strsep(stringp, ", ");
- }
+SWITCH_MODULE_LOAD_FUNCTION(mod_skypiax_load)
+{
- p->skype_friends[0] = '\0';
- }
- }
- } else {
+ module_pool = pool;
- ast_cli(fd,
- "Skype not configured on the 'current' console, not importing from Skype client!\n");
- }
- //}
- /*******************************************************************************************/
- /*******************************************************************************************/
- } else {
- ast_cli(fd, "\n\nfailed to open the skypiax_dir.conf configuration file: %s\n", fn);
- ERRORA("failed to open the skypiax_dir.conf configuration file: %s\n", SKYPIAX_P_LOG,
- fn);
- return RESULT_FAILURE;
- }
+ load_config();
- fclose(p->phonebook_writing_fp);
- //skypiax_dir_create_extensions();
+ *module_interface = switch_loadable_module_create_module_interface(pool, modname);
+ skypiax_endpoint_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE);
+ skypiax_endpoint_interface->interface_name = "skypiax";
+ skypiax_endpoint_interface->io_routines = &skypiax_io_routines;
+ skypiax_endpoint_interface->state_handler = &skypiax_state_handlers;
- return RESULT_SUCCESS;
+
+
+ /* indicate that the module should continue to be loaded */
+ return SWITCH_STATUS_SUCCESS;
}
-#endif /* SKYPIAX_ADDITIONAL */
+
+/*
+SWITCH_MODULE_RUNTIME_FUNCTION(mod_skypiax_runtime)
+{
+ return SWITCH_STATUS_TERM;
+}
+*/
+
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_skypiax_shutdown)
+{
+ int x = 0;
+
+ running = -1;
+
+ while (running) {
+ if (x++ > 100) {
+ break;
+ }
+ switch_yield(20000);
+ }
+ return SWITCH_STATUS_SUCCESS;
+}
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
+ */
+
+#endif /* MOD_SKYPIAX */
More information about the Freeswitch-branches
mailing list