Freeswitch-branches
Threads by month
- ----- 2026 -----
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- 1655 discussions
12 Jan '09
Author: ctrix
Date: Mon Jan 12 17:24:44 2009
New Revision: 11153
Log:
Initial import of airpe...
Not yet fully working, don't expect too much.
Added:
freeswitch/branches/ctrix/mod_airpe/airpe_api.c
freeswitch/branches/ctrix/mod_airpe/airpe_apps.c
freeswitch/branches/ctrix/mod_airpe/airpe_if_common.c
freeswitch/branches/ctrix/mod_airpe/airpe_if_osx.c
freeswitch/branches/ctrix/mod_airpe/airpe_if_win32.c
freeswitch/branches/ctrix/mod_airpe/airpe_if_x11.c
freeswitch/branches/ctrix/mod_airpe/config/
freeswitch/branches/ctrix/mod_airpe/config/airpe.conf.xml
freeswitch/branches/ctrix/mod_airpe/mod_airpe.c
freeswitch/branches/ctrix/mod_airpe/mod_airpe.h
Added: freeswitch/branches/ctrix/mod_airpe/airpe_api.c
==============================================================================
--- (empty file)
+++ freeswitch/branches/ctrix/mod_airpe/airpe_api.c Mon Jan 12 17:24:44 2009
@@ -0,0 +1,262 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct(a)yahoo.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH mod_airpe.
+ *
+ * The Initial Developer of the Original Code is
+ * Massimo Cetra <devel(a)navynet.it>
+ *
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Thanks to gmaruzz for his work on skypiax (both * and freeswitch).
+ * Some of his code inspired this module
+ *
+ */
+
+#include "mod_airpe.h"
+
+#define AIRPE_MOODTEXT_SYNTAX "airpe_moodtext <clientname> <text>"
+SWITCH_STANDARD_API(airpe_moodtext_command)
+{
+ int argc = 0;
+ char *argv[2] = { 0 };
+ char *mycmd = NULL;
+ char *client = NULL;
+ airpe_interface_t *airpe = NULL;
+
+ if (!switch_strlen_zero(cmd) && (mycmd = strdup(cmd))) {
+ argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+ switch_assert(argv[0]);
+ }
+
+ if ( argc < 1 ) {
+ stream->write_function(stream, "-USAGE: %s\n", AIRPE_MOODTEXT_SYNTAX);
+ goto done;
+ }
+
+ client = argv[0];
+ airpe = airpe_find_interface(client);
+
+ if ( !airpe ) {
+ stream->write_function(stream, "-ERR interface not found for client ");
+ stream->write_function(stream, client);
+ stream->write_function(stream, "\n");
+ goto done;
+ }
+
+ if ( argc == 1 ) {
+ stream->write_function(stream, "+OK: ");
+ if ( airpe->mood_text )
+ stream->write_function(stream, airpe->mood_text);
+ else
+ stream->write_function(stream, "UNKNOWN");
+ stream->write_function(stream, "\n");
+ }
+ else {
+ if ( airpe_set_mood_text(airpe, argv[1]) != SWITCH_STATUS_SUCCESS ) {
+ stream->write_function(stream, "-ERR cannot send message to the client\n");
+ goto done;
+ }
+ else {
+ char buf[SKYPE_MSG_LEN];
+ snprintf(buf, SKYPE_MSG_LEN, "SET PROFILE MOOD_TEXT %s", airpe->mood_text );
+ airpe_cmd_write(airpe, buf);
+ }
+ stream->write_function(stream, "+OK mood_text set.\n");
+ }
+
+ done:
+ return SWITCH_STATUS_SUCCESS;
+}
+
+#define AIRPE_INFO_SYNTAX "airpe_status <clientname>"
+SWITCH_STANDARD_API(airpe_info_command)
+{
+ int argc = 0;
+ char *argv[4] = { 0 };
+ char *mycmd = NULL;
+ char *client = NULL;
+ char buf[512];
+ airpe_interface_t *airpe = NULL;
+
+ if (!switch_strlen_zero(cmd) && (mycmd = strdup(cmd))) {
+ argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+ switch_assert(argv[0]);
+ }
+
+ if ( argc < 1 ) {
+ stream->write_function(stream, "-USAGE: %s\n", AIRPE_INFO_SYNTAX);
+ goto done;
+ }
+
+ client = argv[0];
+ airpe = airpe_find_interface(client);
+
+ if ( !airpe ) {
+ stream->write_function(stream, "-ERR interface not found for client ");
+ stream->write_function(stream, client);
+ stream->write_function(stream, "\n");
+ goto done;
+ }
+
+ switch_snprintf(buf, sizeof(buf), "%-20s: %s\n", "Client name", airpe->name);
+ stream->write_function(stream, buf);
+ switch_snprintf(buf, sizeof(buf), "%-20s: %s\n", "Dialplan", airpe->dialplan);
+ stream->write_function(stream, buf);
+ switch_snprintf(buf, sizeof(buf), "%-20s: %s\n", "Context", airpe->context);
+ stream->write_function(stream, buf);
+ switch_snprintf(buf, sizeof(buf), "%-20s: %s\n", "Destination", airpe->destination);
+ stream->write_function(stream, buf);
+ switch_snprintf(buf, sizeof(buf), "%-20s: %s\n", "Skype username", airpe->skype_user);
+ stream->write_function(stream, buf);
+ if ( airpe->audio_in_port > 0 )
+ switch_snprintf(buf, sizeof(buf), "%-20s: %d\n", "Audio in port", airpe->audio_in_port);
+ else
+ switch_snprintf(buf, sizeof(buf), "%-20s: %s\n", "Audio in port", "NOT SET");
+ stream->write_function(stream, buf);
+ if ( airpe->audio_in_port > 0 )
+ switch_snprintf(buf, sizeof(buf), "%-20s: %d\n", "Audio out port", airpe->audio_out_port);
+ else
+ switch_snprintf(buf, sizeof(buf), "%-20s: %s\n", "Audio out port", "NOT SET");
+ stream->write_function(stream, buf);
+
+ switch_snprintf(buf, sizeof(buf), "%-20s: %s\n", "Connection status", skype_conn_status_string(airpe->conn_status) );
+ stream->write_function(stream, buf);
+ switch_snprintf(buf, sizeof(buf), "%-20s: %s\n", "Client status", skype_user_status_string(airpe->user_status) );
+ stream->write_function(stream, buf);
+
+ switch_snprintf(buf, sizeof(buf), "%-20s: %s\n", "Skype version", (airpe->skype_version) ? airpe->skype_version : "Unknown" );
+ stream->write_function(stream, buf);
+ switch_snprintf(buf, sizeof(buf), "%-20s: %s\n", "Mood text", (airpe->mood_text ) ? airpe->mood_text : "Unknown" );
+ stream->write_function(stream, buf);
+
+ done:
+ return SWITCH_STATUS_SUCCESS;
+}
+
+#define AIRPE_STATUS_SYNTAX "airpe_status <clientname> <status>"
+SWITCH_STANDARD_API(airpe_status_command)
+{
+ int argc = 0;
+ char *argv[4] = { 0 };
+ char *mycmd = NULL;
+ char *client = NULL;
+ char *cstatus= NULL;
+ airpe_interface_t *airpe = NULL;
+
+ if (!switch_strlen_zero(cmd) && (mycmd = strdup(cmd))) {
+ argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+ switch_assert(argv[0]);
+ }
+
+ if ( argc < 1 ) {
+ stream->write_function(stream, "-USAGE: %s\n", AIRPE_STATUS_SYNTAX);
+ goto done;
+ }
+
+ client = argv[0];
+ if ( argc > 1 )
+ cstatus = argv[1];
+
+ airpe = airpe_find_interface(client);
+
+ if ( !airpe ) {
+ stream->write_function(stream, "-ERR interface not found: \n");
+ stream->write_function(stream, client);
+ stream->write_function(stream, "\n");
+ goto done;
+ }
+
+ if ( !cstatus ) {
+ const char *str_status = NULL;
+ str_status = skype_user_status_string( airpe->user_status );
+ stream->write_function(stream, "+OK status is ");
+ if ( str_status )
+ stream->write_function(stream, str_status);
+ else
+ stream->write_function(stream, "... uhmmm, ehmm, DUNNO... ");
+ stream->write_function(stream, "\n");
+ }
+ else {
+ char buf[SKYPE_MSG_LEN];
+ const char *str_status = NULL;
+
+ if ( !strncasecmp(cstatus, "unknown", sizeof("unknown") ) )
+ str_status = skype_user_status_string(USER_STATUS_UNKNOWN);
+ else if ( !strncasecmp(cstatus, "online", sizeof("online") ) )
+ str_status = skype_user_status_string(USER_STATUS_ONLINE);
+ else if ( !strncasecmp(cstatus, "offline", sizeof("offline") ) )
+ str_status = skype_user_status_string(USER_STATUS_OFFLINE);
+ else if ( !strncasecmp(cstatus, "skypeme", sizeof("skypeme") ) )
+ str_status = skype_user_status_string(USER_STATUS_SKYPEME);
+ else if ( !strncasecmp(cstatus, "away", sizeof("away") ) )
+ str_status = skype_user_status_string(USER_STATUS_AWAY);
+ else if ( !strncasecmp(cstatus, "na", sizeof("na") ) )
+ str_status = skype_user_status_string(USER_STATUS_NA);
+ else if ( !strncasecmp(cstatus, "dnd", sizeof("dnd") ) )
+ str_status = skype_user_status_string(USER_STATUS_DND);
+ else if ( !strncasecmp(cstatus, "invisible", sizeof("invisible") ) )
+ str_status = skype_user_status_string(USER_STATUS_INVISIBLE);
+ else if ( !strncasecmp(cstatus, "loggedout", sizeof("loggedout") ) )
+ str_status = skype_user_status_string(USER_STATUS_LOGGEDOUT);
+
+ if ( str_status ) {
+ snprintf(buf, SKYPE_MSG_LEN, "SET USERSTATUS %s", cstatus );
+ if ( airpe_cmd_write(airpe, buf) != SWITCH_STATUS_SUCCESS ) {
+ stream->write_function(stream, "-ERR cannot send message to the client\n");
+ goto done;
+ }
+ stream->write_function(stream, "+OK status set.\n");
+ }
+ else {
+ stream->write_function(stream, "-ERR invalid status string\n");
+ }
+ }
+
+ done:
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+
+switch_status_t airpe_register_api( switch_loadable_module_interface_t **module_interface ) {
+
+ switch_api_interface_t *api;
+
+ switch_console_set_complete("add airpe_moodtext ");
+ SWITCH_ADD_API(api, "airpe_moodtext", "sets the mood text of an airpe client", airpe_moodtext_command, AIRPE_MOODTEXT_SYNTAX);
+
+ switch_console_set_complete("add airpe_info ");
+ SWITCH_ADD_API(api, "airpe_info", "shows the status of an airpe client", airpe_info_command, AIRPE_INFO_SYNTAX);
+
+ switch_console_set_complete("add airpe_status ");
+ SWITCH_ADD_API(api, "airpe_status", "sets the status of an airpe client", airpe_status_command, AIRPE_STATUS_SYNTAX);
+
+ 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:
+ */
Added: freeswitch/branches/ctrix/mod_airpe/airpe_apps.c
==============================================================================
--- (empty file)
+++ freeswitch/branches/ctrix/mod_airpe/airpe_apps.c Mon Jan 12 17:24:44 2009
@@ -0,0 +1,56 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct(a)yahoo.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH mod_airpe.
+ *
+ * The Initial Developer of the Original Code is
+ * Massimo Cetra <devel(a)navynet.it>
+ *
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Thanks to gmaruzz for his work on skypiax (both * and freeswitch).
+ * Some of his code inspired this module
+ *
+ */
+
+#include "mod_airpe.h"
+
+SWITCH_STANDARD_APP(airpe_app_test)
+{
+}
+
+
+switch_status_t airpe_register_apps( switch_loadable_module_interface_t **module_interface ) {
+ switch_application_interface_t *app_interface;
+
+ SWITCH_ADD_APP(app_interface, "airpe_test", "test text", "test text", airpe_app_test, "", SAF_SUPPORT_NOMEDIA);
+
+ 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:
+ */
+
Added: freeswitch/branches/ctrix/mod_airpe/airpe_if_common.c
==============================================================================
--- (empty file)
+++ freeswitch/branches/ctrix/mod_airpe/airpe_if_common.c Mon Jan 12 17:24:44 2009
@@ -0,0 +1,770 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct(a)yahoo.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH mod_airpe.
+ *
+ * The Initial Developer of the Original Code is
+ * Massimo Cetra <devel(a)navynet.it>
+ *
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Thanks to gmaruzz for his work on skypiax (both * and freeswitch).
+ * Some of his code inspired this module
+ *
+ */
+
+#include "mod_airpe.h"
+
+static struct {
+ USER_STATUS status;
+ const char *name;
+} user_status_names[] = {
+ { USER_STATUS_UNKNOWN, "UNKNOWN" },
+ { USER_STATUS_ONLINE, "ONLINE" },
+ { USER_STATUS_OFFLINE, "OFFLINE" },
+ { USER_STATUS_SKYPEME, "SKYPEME" },
+ { USER_STATUS_AWAY, "AWAY" },
+ { USER_STATUS_NA, "NA" },
+ { USER_STATUS_DND, "DND" },
+ { USER_STATUS_INVISIBLE, "INVISIBLE" },
+ { USER_STATUS_LOGGEDOUT, "LOGGEDOUT" },
+};
+
+static struct {
+ CONN_STATUS status;
+ const char *name;
+} connection_status_names[] = {
+ { CONN_STATUS_UNKNOWN, "UNKNOWN" },
+ { CONN_STATUS_OFFLINE, "OFFLINE" },
+ { CONN_STATUS_CONNECTING, "CONNECTING" },
+ { CONN_STATUS_PAUSING, "PAUSING" },
+ { CONN_STATUS_ONLINE, "ONLINE" },
+};
+
+/* ************************************************************************* */
+
+const char *skype_user_status_string(USER_STATUS st) {
+ int t;
+ const char *ret = NULL;
+
+ for ( t = 0; t < sizeof(user_status_names) / sizeof(user_status_names[0]); t++ ) {
+ if ( user_status_names[t].status == st ) {
+ ret = user_status_names[t].name;
+ break;
+ }
+ }
+ return ret;
+}
+
+USER_STATUS skype_user_status(const char *str) {
+ int t;
+ USER_STATUS ret = USER_STATUS_UNKNOWN;
+
+ for ( t = 0; t < sizeof(user_status_names) / sizeof(user_status_names[0]); t++ ) {
+ if ( !strncasecmp(user_status_names[t].name, str, strlen(user_status_names[t].name) ) ) {
+ ret = user_status_names[t].status;
+ break;
+ }
+ }
+ return ret;
+}
+
+/* ************************************************************************* */
+
+const char *skype_conn_status_string(CONN_STATUS st) {
+ int t;
+ const char *ret = NULL;
+
+ for ( t = 0; t < sizeof(connection_status_names) / sizeof(connection_status_names[0]); t++ ) {
+ if ( connection_status_names[t].status == st ) {
+ ret = connection_status_names[t].name;
+ break;
+ }
+ }
+ return ret;
+}
+
+CONN_STATUS skype_conn_status(const char *str) {
+ int t;
+ CONN_STATUS ret = CONN_STATUS_UNKNOWN;
+
+ for ( t = 0; t < sizeof(connection_status_names) / sizeof(connection_status_names[0]); t++ ) {
+ if ( !strncasecmp(connection_status_names[t].name, str, strlen(connection_status_names[t].name) ) ) {
+ ret = connection_status_names[t].status;
+ break;
+ }
+ }
+ return ret;
+}
+
+/* ************************************************************************* */
+
+switch_status_t airpe_set_version(airpe_interface_t *airpe, char *string) {
+ assert(airpe);
+ switch_safe_free(airpe->skype_version);
+ if ( string )
+ airpe->skype_version = strdup(string);
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t airpe_set_mood_text(airpe_interface_t *airpe, char *string) {
+ assert(airpe);
+ switch_safe_free(airpe->mood_text);
+ if ( string )
+ airpe->mood_text = strdup(string);
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t airpe_set_partner_displayname(airpe_interface_t *airpe, char *string) {
+ assert(airpe);
+ switch_safe_free(airpe->partner_displayname);
+ if ( string )
+ airpe->partner_displayname = strdup(string);
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t airpe_set_partner_handle(airpe_interface_t *airpe, char *string) {
+ assert(airpe);
+ switch_safe_free(airpe->partner_handle);
+ if ( string )
+ airpe->partner_handle = strdup(string);
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t airpe_cmd_write(airpe_interface_t *airpe, char *msg) {
+ if ( airpe->debug )
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "msg to airpe client %s: %s\n", airpe->name, msg);
+ return airpe_skype_send_message(airpe->skype_window, msg);
+}
+
+switch_status_t airpe_originate(airpe_interface_t *airpe, char *dest) {
+ char msg[SKYPE_MSG_LEN];
+
+ /*
+ Those commands are outdated and shouldn't be used
+ Documented so that no one adds them.
+ airpe_cmd_write(p, "SET AGC OFF");
+ airpe_cmd_write(p, "SET AEC OFF");
+ */
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "airpe client %s: Originating to %s\n", airpe->name, dest);
+
+ snprintf(msg, sizeof(msg), "CALL %s", dest);
+
+ if ( (airpe_cmd_write(airpe, msg) != SWITCH_STATUS_SUCCESS) ) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t airpe_explicit_hangup(airpe_interface_t *airpe) {
+ char buf[SKYPE_MSG_LEN];
+
+ if ( airpe->active_call_id > 0 ) {
+ snprintf(buf, sizeof(buf), "SET CALL %d STATUS FINISHED", airpe->active_call_id);
+ return airpe_cmd_write(airpe, buf);
+ }
+ return SWITCH_STATUS_FALSE;
+}
+
+
+
+/*****************************************************************************
+ SKYPE AUDIO
+ *****************************************************************************/
+
+switch_status_t airpe_hangup( private_object_t *pvt ) {
+ airpe_interface_t *airpe;
+
+ assert(pvt);
+ assert(pvt->session);
+ assert(pvt->airpe);
+
+ airpe = pvt->airpe;
+
+ if ( airpe->audio_in_active_socket ) {
+ switch_socket_shutdown(airpe->audio_in_active_socket, SWITCH_SHUTDOWN_READWRITE);
+ switch_socket_close(airpe->audio_in_active_socket);
+ airpe->audio_in_active_socket = 0;
+ }
+
+ if ( airpe->audio_out_active_socket ) {
+ switch_socket_shutdown(airpe->audio_out_active_socket, SWITCH_SHUTDOWN_READWRITE);
+ switch_socket_close(airpe->audio_out_active_socket);
+ airpe->audio_out_active_socket = 0;
+ }
+
+ airpe->tech_pvt = NULL;
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t airpe_audio_write( private_object_t *pvt, switch_frame_t *frame ) {
+ switch_socket_t *inbound_socket = NULL;
+ switch_memory_pool_t *pool;
+ airpe_interface_t *airpe;
+ switch_status_t rv;
+ switch_size_t mlen;
+ char *mbuf;
+
+ assert(pvt);
+ assert(pvt->session);
+ assert(pvt->airpe);
+
+ airpe = pvt->airpe;
+ pool = switch_core_session_get_pool(pvt->session);
+
+ if ( !airpe->audio_in_active_socket ) {
+ rv = switch_socket_accept(&inbound_socket, airpe->audio_in_socket, pool);
+ if ( rv == SWITCH_STATUS_SUCCESS ) {
+ airpe->audio_in_active_socket = inbound_socket;
+ switch_sleep(100000);
+ }
+ else {
+ return SWITCH_STATUS_FALSE;
+ }
+ }
+
+ mbuf = frame->data;
+ mlen = frame->datalen;
+ rv = switch_socket_send(airpe->audio_in_active_socket, mbuf, &mlen);
+
+ return rv;
+}
+
+switch_status_t airpe_audio_read( private_object_t *pvt ) {
+ switch_socket_t *inbound_socket = NULL;
+ switch_memory_pool_t *pool;
+ airpe_interface_t *airpe;
+ switch_status_t rv;
+ switch_size_t mlen;
+ char *ptr;
+
+ assert(pvt);
+ assert(pvt->session);
+ assert(pvt->airpe);
+
+ airpe = pvt->airpe;
+ pool = switch_core_session_get_pool(pvt->session);
+
+ if ( !airpe->audio_out_active_socket ) {
+ rv = switch_socket_accept(&inbound_socket, airpe->audio_out_socket, pool);
+ if ( rv == SWITCH_STATUS_SUCCESS ) {
+ airpe->audio_out_active_socket = inbound_socket;
+ switch_sleep(100000);
+ }
+ else {
+ return SWITCH_STATUS_FALSE;
+ }
+ }
+
+ pvt->read_frame.datalen = 0;
+ ptr = pvt->read_frame.data;
+ mlen = sizeof(pvt->databuf);
+ rv = switch_socket_recv(airpe->audio_out_active_socket, ptr, &mlen);
+
+ if ( (rv==SWITCH_STATUS_SUCCESS) ) {
+ pvt->read_frame.datalen = mlen;
+ }
+// if ( mlen == 0 )
+// return SWITCH_STATUS_SUCCESS;
+
+ return rv;
+}
+
+/*****************************************************************************
+ SKYPE CONTROL MESSAGES
+ *****************************************************************************/
+
+static switch_status_t airpe_manage_incoming_call( airpe_interface_t *airpe, int callid ) {
+ char chan_name[256];
+ switch_channel_t *channel = NULL;
+ switch_core_session_t *new_session = NULL;
+ private_object_t *tech_pvt = NULL;
+
+ new_session = airpe_request_session(NULL);
+ if ( !new_session ) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ switch_core_session_add_stream(new_session, NULL);
+
+ tech_pvt = (private_object_t *) switch_core_session_alloc(new_session, sizeof(private_object_t));
+ if ( !tech_pvt ) {
+ switch_core_session_destroy(&new_session);
+ return SWITCH_STATUS_FALSE;
+ }
+ memset(tech_pvt, 0, sizeof(private_object_t));
+
+ channel = switch_core_session_get_channel(new_session);
+ assert(channel);
+
+ if ( airpe_tech_init(tech_pvt, new_session) != SWITCH_STATUS_SUCCESS ) {
+ switch_core_session_destroy(&new_session);
+ return SWITCH_STATUS_FALSE;
+ }
+ tech_pvt->airpe = airpe;
+
+ switch_snprintf(chan_name, sizeof(chan_name), MODNAME"/%s", airpe->name);
+ switch_channel_set_name(channel, chan_name);
+
+ tech_pvt->caller_profile = switch_caller_profile_new( switch_core_session_get_pool(new_session),
+ airpe->name, /* Username */
+ airpe->dialplan, /* Diaplan */
+ airpe->partner_displayname, /* cid_name */
+ airpe->partner_handle, /* cid_number */
+ NULL, /* network_addr */
+ NULL, /* ani */
+ NULL, /* aniii */
+ NULL, /* rdnis */
+ MODNAME, /* source */
+ airpe->context, /* context */
+ airpe->destination /* destination_number */
+ );
+
+ if ( !tech_pvt->caller_profile ) {
+ switch_core_session_destroy(&new_session);
+ return SWITCH_STATUS_FALSE;
+ }
+ else
+ switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
+
+
+ switch_set_flag(tech_pvt, TFLAG_INBOUND);
+ airpe->active_call_id = callid;
+ switch_channel_set_state(channel, CS_INIT);
+
+ if ( switch_core_session_thread_launch(new_session) != SWITCH_STATUS_SUCCESS ) {
+ airpe->active_call_id = 0;
+ switch_core_session_destroy(&new_session);
+ return SWITCH_STATUS_FALSE;
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t airpe_manage_call_status( airpe_interface_t *airpe, int callid, const char *status ) {
+ char buf[SKYPE_MSG_LEN];
+ switch_core_session_t *session = NULL;
+ switch_channel_t *channel = NULL;
+
+ if ( airpe->active_call_id && airpe->active_call_id != callid ) {
+ADEBUG("CASE 1 - different call\n");
+ if ( !strncmp(status, "UNPLACED", strlen("UNPLACED")) ) {
+ snprintf(buf, sizeof(buf), "SET CALL %d STATUS FINISHED", callid);
+ airpe_cmd_write(airpe, buf);
+ }
+ else {
+ ADEBUG("*** (%d/%d) Unmanaged status %s\n", airpe->active_call_id, callid, status);
+ }
+
+ }
+ else if ( airpe->active_call_id && airpe->active_call_id == callid ) {
+ADEBUG("CASE 2 - my call\n");
+ if ( airpe->tech_pvt ) {
+ assert(airpe->tech_pvt);
+ session = airpe->tech_pvt->session;
+ assert(session);
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel);
+ }
+
+ if ( !strncmp(status, "ROUTING", strlen("ROUTING")) ) {
+ }
+ else if ( !strncmp(status, "RINGING", strlen("RINGING")) ) {
+ //if ( switch_test_flag(tech_pvt, TFLAG_OUTBOUND) ) {
+ //switch_channel_set_state(channel, CS_RINGING);
+ switch_core_session_queue_indication(session, SWITCH_MESSAGE_INDICATE_RINGING);
+ switch_channel_mark_ring_ready(channel);
+ //}
+
+ snprintf(buf, sizeof(buf), "ALTER CALL %d SET_INPUT PORT=\"%d\"", callid, airpe->audio_in_port);
+ airpe_cmd_write(airpe, buf);
+ snprintf(buf, sizeof(buf), "ALTER CALL %d SET_OUTPUT PORT=\"%d\"", callid, airpe->audio_out_port);
+ airpe_cmd_write(airpe, buf);
+
+
+
+ switch_channel_set_state(channel, CS_ROUTING);
+
+ }
+ else if ( !strncmp(status, "INPROGRESS", strlen("INPROGRESS")) ) {
+ snprintf(buf, sizeof(buf), "ALTER CALL %d STOP_VIDEO_SEND", callid );
+ airpe_cmd_write(airpe, buf);
+ snprintf(buf, sizeof(buf), "ALTER CALL %d STOP_VIDEO_RECEIVE", callid );
+ airpe_cmd_write(airpe, buf);
+
+ if ( channel ) {
+ switch_channel_mark_answered(channel);
+ }
+ else {
+ if ( airpe_manage_incoming_call(airpe, callid) != SWITCH_STATUS_SUCCESS ) {
+ snprintf(buf, sizeof(buf), "ALTER CALL %d END HANGUP", callid );
+ airpe_cmd_write(airpe, buf);
+ airpe->active_call_id = 0;
+ }
+ }
+ }
+ else if ( !strncmp(status, "FINISHED", strlen("FINISHED")) ) {
+ if ( channel )
+ switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
+ airpe->active_call_id = 0;
+ }
+ else if ( !strncmp(status, "FAILED", strlen("FAILED")) ) {
+ if ( channel )
+ switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
+ airpe->active_call_id = 0;
+ }
+ else if ( !strncmp(status, "CANCELLED", strlen("CANCELLED")) ) {
+ if ( channel )
+ switch_channel_hangup(channel, SWITCH_CAUSE_ORIGINATOR_CANCEL);
+ airpe->active_call_id = 0;
+ }
+ else if ( !strncmp(status, "REFUSED", strlen("REFUSED")) ) {
+ if ( channel )
+ switch_channel_hangup(channel, SWITCH_CAUSE_CALL_REJECTED);
+ airpe->active_call_id = 0;
+ }
+ else if ( !strncmp(status, "MISSED", strlen("MISSED")) ) {
+ if ( channel )
+ switch_channel_hangup(channel, SWITCH_CAUSE_NO_ANSWER);
+ airpe->active_call_id = 0;
+ }
+ else if ( !strncmp(status, "UNPLACED", strlen("UNPLACED")) ) {
+ }
+ else {
+ADEBUG("Unmanaged status \n");
+ }
+ }
+ else {
+ADEBUG("CASE 3 - no calls online\n");
+ if ( !strncmp(status, "UNPLACED", strlen("UNPLACED")) ) {
+ airpe->active_call_id = callid;
+ }
+ else if ( !strncmp(status, "RINGING", strlen("RINGING")) ) {
+ airpe->active_call_id = callid;
+ snprintf(buf, sizeof(buf), "ALTER CALL %d ANSWER", callid );
+ airpe_cmd_write(airpe, buf);
+ }
+ else {
+ ADEBUG("--- (%d/%d) Unmanaged status %s\n", airpe->active_call_id, callid, status);
+ }
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t airpe_manage_skype_msg( airpe_interface_t *airpe, const char *msg ) {
+ char *buf = NULL;
+ int argc = 0;
+ char *argv[9] = { 0 };
+
+ assert(airpe);
+ assert(msg);
+
+ if ( airpe->debug )
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "airpe client %s: %s\n", airpe->name, msg);
+
+ buf = strdup(msg);
+ argc = switch_separate_string(buf, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+
+ if ( argc == 0 ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "airpe client %s: %s - Message without arguments? uh?\n", airpe->name, msg);
+ free(buf);
+ return SWITCH_STATUS_FALSE;
+ }
+
+
+
+ if ( !strncmp( buf, "CURRENTUSERHANDLE", strlen("CURRENTUSERHANDLE")) ) {
+ /* The username that the client is using. */
+ // TODO ... if the user handle mismatches, disconnect the channel or simply disable
+ // all operations
+ }
+ else if ( !strncmp( buf, "USERSTATUS", strlen("USERSTATUS")) && argc > 1 ) {
+ /* The status of the user of the client (ex: NA, ONLINE) */
+ airpe->user_status = skype_user_status(argv[1]);
+ }
+ else if ( !strncmp( buf, "PROTOCOL", strlen("PROTOCOL")) && argc > 1 ) {
+ /* The protocol of the client */
+ airpe->protocol = atoi(argv[1]);
+ }
+ else if ( !strncmp( buf, "CLEAR", strlen("CLEAR")) ) {
+ /* something has been cleared in the UI - Ignored */
+ }
+ else if ( !strncmp( buf, "PONG", strlen("PONG")) ) {
+ /* keepalive */
+ airpe_skype_watchdog_reset(airpe->skype_window);
+ }
+ else if ( !strncmp( buf, "CONNSTATUS", strlen("CONNSTATUS")) && argc >= 2 ) {
+ /* The connection status of the client (ex: ONLINE) */
+ airpe->conn_status = skype_conn_status( argv[1] );
+ }
+ else if ( !strncmp( buf, "USER", strlen("USER")) ) {
+ /* Updates about the users of our list - ignored */
+ }
+ else if ( !strncmp( buf, "GROUP", strlen("GROUP")) ) {
+ /* Updates about the groups of our list - ignored */
+ }
+ else if ( !strncmp( buf, "CONTACTS", strlen("CONTACTS")) ) {
+ /* Other messages referring to the contact list - ignored */
+ }
+ else if ( !strncmp( buf, "OK", strlen("OK")) ) {
+ /* Acknowledge - ignored */
+ }
+ else if ( !strncmp( buf, "AUTOAWAY", strlen("AUTOAWAY")) ) {
+ /* Autoaway - ignored */
+ }
+//TODO: RECEIVEDAUTHREQUEST - Add a config option to authorize or forget about it.
+ else if ( !strncmp( buf, "MUTE", strlen("MUTE")) && argc >= 2 ) {
+ if ( !strncmp(argv[1], "ON", 2) ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "airpe client %s: I don't like to be muted...\n", airpe->name);
+ airpe_cmd_write(airpe, "MUTE OFF");
+ }
+ }
+ else if ( !strncmp( buf, "CHATMESSAGE", strlen("CHATMESSAGE")) ) {
+ /* a message has been received (unknown content) - ignored */
+ }
+ else if ( !strncmp( buf, "CHAT", strlen("CHAT")) && argc >=2 ) {
+ /* Chat status - ignored. */
+ if ( airpe->protocol > 6 ) {
+ //TODO : ALTER CHAT <chat_id> DISBAND - Doesn't seems to work on linux
+ char buf[SKYPE_MSG_LEN] = "";
+ snprintf(buf, sizeof(buf), "ALTER CHAT %s DISBAND", argv[1]);
+ airpe_cmd_write(airpe, buf);
+ }
+ }
+ else if ( !strncmp( buf, "CHATMEMBER", strlen("CHATMEMBER")) ) {
+ /* Informations about the chat members - ignored */
+ }
+ else if ( !strncmp( buf, "PROFILE", strlen("PROFILE")) && argc >= 2 ) {
+ if ( !strncmp(argv[1], "MOOD_TEXT", strlen("MOOD_TEXT")) ) {
+ char *tmp = NULL;
+ char *mood;
+ tmp = strdup(msg);
+ if ( tmp ) {
+ mood = strstr(tmp, "PROFILE MOOD_TEXT ");
+ if ( mood ) {
+ mood += strlen("PROFILE MOOD_TEXT ");
+ airpe_set_mood_text(airpe, mood);
+ }
+ switch_safe_free(tmp);
+ }
+ }
+ }
+ else if ( !strncmp( buf, "SKYPEVERSION", strlen("SKYPEVERSION")) ) {
+ airpe_set_version(airpe, argv[1]);
+ }
+ else if ( !strncmp( buf, "CALL", strlen("CALL")) && argc >= 3 ) {
+ char *cmd = argv[2];
+ int callid = atoi(argv[1]);
+
+ if ( !strncmp(cmd, "DURATION", strlen("DURATION")) ) {
+ /* Ignore the duration that is updated every second */
+ if ( callid != airpe->active_call_id ) {
+ char buf[SKYPE_MSG_LEN] = "";
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "airpe client %s: hanging up unknown call id %d\n", airpe->name, callid);
+ snprintf(buf, sizeof(buf), "SET CALL %d STATUS FINISHED", callid);
+ airpe_cmd_write(airpe, buf);
+ }
+ //TODO: maybe we could consider this message as a keepalive signal
+ }
+ else if ( !strncmp(cmd, "STATUS", strlen("STATUS")) && argc >=4 ) {
+ char *callstatus = argv[3];
+ airpe_manage_call_status( airpe, callid, callstatus );
+ }
+ else if ( !strncmp(cmd, "CONF_ID", strlen("CONF_ID")) ) {
+ char buf[SKYPE_MSG_LEN];
+
+ if ( !airpe->active_call_id ) {
+ airpe_set_partner_displayname(airpe, NULL);
+ airpe_set_partner_handle(airpe, NULL);
+
+ snprintf(buf, sizeof(buf), "GET CALL %d PARTNER_DISPNAME", callid);
+ airpe_cmd_write(airpe, buf);
+
+ snprintf(buf, sizeof(buf), "GET CALL %d PARTNER_HANDLE", callid);
+ airpe_cmd_write(airpe, buf);
+
+ airpe_cmd_write(airpe, "PING");
+ }
+ else {
+ snprintf(buf, sizeof(buf), "ALTER CALL %d END HANGUP", callid );
+ airpe_cmd_write(airpe, buf);
+ }
+ }
+ else if ( !strncmp(cmd, "VAA_INPUT_STATUS", strlen("VAA_INPUT_STATUS")) ) {
+ /* Let's ignore */
+ }
+ else if ( !strncmp(cmd, "DTMF", strlen("DTMF")) ) {
+ /* This is an incoming DTMF */
+ switch_core_session_t *session;
+ switch_channel_t *channel;
+ switch_dtmf_t dtmf = { 0, switch_core_default_dtmf_duration(0) };
+ const char *signal_ptr;
+ int tmp;
+
+ assert(airpe->tech_pvt);
+ session = airpe->tech_pvt->session;
+ assert(session);
+ channel = switch_core_session_get_channel(session);
+ assert(channel);
+
+ signal_ptr = argv[3];
+
+ if (*signal_ptr && (*signal_ptr == '*' || *signal_ptr == '#' || *signal_ptr == 'A' || *signal_ptr == 'B' || *signal_ptr == 'C' || *signal_ptr == 'D')) {
+ dtmf.digit = *signal_ptr;
+ } else {
+ tmp = atoi(signal_ptr);
+ dtmf.digit = switch_rfc2833_to_char(tmp);
+ }
+
+ switch_mutex_lock(airpe->tech_pvt->flag_mutex);
+ switch_channel_queue_dtmf(channel, &dtmf);
+ switch_mutex_unlock(airpe->tech_pvt->flag_mutex);
+ }
+ else if ( !strncmp(cmd, "FAILUREREASON", strlen("FAILUREREASON")) && argc >=2 ) {
+ airpe->last_fail_reason = atoi(argv[1]);
+ airpe_cmd_write(airpe, "CLEAR CALLHISTORY ALL");
+ }
+ else if ( !strncmp(cmd, "SEEN", strlen("SEEN")) && argc >=4 ) {
+ /*
+ char buf[SKYPE_MSG_LEN] = "";
+ char *seenstatus = argv[3];
+ if ( !strncmp(seenstatus, "FALSE", strlen("FALSE")) ) {
+ snprintf(buf, sizeof(buf), "SET CALL %d SEEN", callid);
+ airpe_cmd_write(airpe, buf);
+ }
+ */
+ airpe_cmd_write(airpe, "CLEAR CALLHISTORY ALL");
+ }
+ else if ( !strncmp(cmd, "PARTNER_DISPNAME", strlen("PARTNER_DISPNAME")) && argc >=2 ) {
+ char *data, *tmp = NULL;
+ tmp = strdup(msg);
+ if ( tmp && (callid == airpe->active_call_id) ) {
+ data = strstr(tmp, "PARTNER_DISPNAME ");
+ if ( data ) {
+ data += strlen("PARTNER_DISPNAME ");
+ airpe_set_partner_displayname(airpe, data);
+ }
+ }
+ switch_safe_free(tmp);
+ }
+ else if ( !strncmp(cmd, "PARTNER_HANDLE", strlen("PARTNER_HANDLE")) && argc >=2 ) {
+ char *data, *tmp = NULL;
+ tmp = strdup(msg);
+ if ( tmp && (callid == airpe->active_call_id) ) {
+ data = strstr(tmp, "PARTNER_HANDLE ");
+ if ( data ) {
+ data += strlen("PARTNER_HANDLE ");
+ airpe_set_partner_handle(airpe, data);
+ }
+ switch_safe_free(tmp);
+ }
+ }
+ else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "CALL ID %d\n", callid);
+ }
+ }
+ else if ( !strncmp( buf, "DTMF", strlen("DTMF")) && argc>3 ) {
+ /* We are alerted that a DTMF we was sent to the other party - Ignored */
+ }
+ else if ( !strncmp( msg, "ERROR 68", strlen("ERROR 68")) ) {
+ /* The client needs authorization. Probably we reconnected to a new skype window. */
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Airpe client %s needs authorization.\n", airpe->name);
+ switch_sleep(1000000);
+ airpe_on_connect_messages(airpe, airpe->protocol);
+ }
+ else if ( !strncmp( msg, "ALTER CALL", strlen("ALTER CALL")) ) {
+ /* The response to our hangup - Ignored */
+ }
+ else if ( !strncmp( msg, "SET CALL", strlen("SET CALL")) ) {
+ /* Ignoring by now */
+ }
+ else if ( !strncmp( buf, "ERROR", strlen("ERROR")) ) {
+ //TODO If we are in the middle of a call, hangup
+ }
+ else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unmanaged message\n");
+ }
+
+ switch_safe_free(buf);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t airpe_on_connect_messages( airpe_interface_t *airpe, int protocol ) {
+ char buf[SKYPE_MSG_LEN] = "";
+
+ snprintf(buf, sizeof(buf), "NAME airpe");
+ if ( airpe_cmd_write(airpe, buf) != SWITCH_STATUS_SUCCESS )
+ return SWITCH_STATUS_FALSE;
+ snprintf(buf, sizeof(buf), "PROTOCOL %d", protocol);
+ if ( airpe_cmd_write(airpe, buf) != SWITCH_STATUS_SUCCESS )
+ return SWITCH_STATUS_FALSE;
+ snprintf(buf, sizeof(buf), "CLEAR CALLHISTORY ALL");
+ if ( airpe_cmd_write(airpe, buf) != SWITCH_STATUS_SUCCESS )
+ return SWITCH_STATUS_FALSE;
+ snprintf(buf, sizeof(buf), "CLEAR CHATHISTORY");
+ if ( airpe_cmd_write(airpe, buf) != SWITCH_STATUS_SUCCESS )
+ return SWITCH_STATUS_FALSE;
+ snprintf(buf, sizeof(buf), "GET SKYPEVERSION");
+ if ( airpe_cmd_write(airpe, buf) != SWITCH_STATUS_SUCCESS )
+ return SWITCH_STATUS_FALSE;
+ snprintf(buf, sizeof(buf), "GET PROFILE MOOD_TEXT");
+ if ( airpe_cmd_write(airpe, buf) != SWITCH_STATUS_SUCCESS )
+ return SWITCH_STATUS_FALSE;
+ snprintf(buf, sizeof(buf), "GET PROFILE FULLNAME");
+ if ( airpe_cmd_write(airpe, buf) != SWITCH_STATUS_SUCCESS )
+ return SWITCH_STATUS_FALSE;
+ snprintf(buf, sizeof(buf), "GET CONNSTATUS");
+ if ( airpe_cmd_write(airpe, buf) != SWITCH_STATUS_SUCCESS )
+ return SWITCH_STATUS_FALSE;
+ snprintf(buf, sizeof(buf), "SET AUTOAWAY OFF");
+ if ( airpe_cmd_write(airpe, buf) != SWITCH_STATUS_SUCCESS )
+ return SWITCH_STATUS_FALSE;
+ snprintf(buf, sizeof(buf), "SET MUTE OFF");
+ if ( airpe_cmd_write(airpe, buf) != SWITCH_STATUS_SUCCESS )
+ return SWITCH_STATUS_FALSE;
+
+ /*
+ The following two raise an error on linux, even if are supported from protocol 6 upwards.
+ That's not a big problem so we'll send them.
+ */
+
+ snprintf(buf, sizeof(buf), "SET PCSPEAKER OFF");
+ if ( airpe_cmd_write(airpe, buf) != SWITCH_STATUS_SUCCESS )
+ return SWITCH_STATUS_FALSE;
+ snprintf(buf, sizeof(buf), "SET SILENT_MODE ON");
+ if ( airpe_cmd_write(airpe, buf) != SWITCH_STATUS_SUCCESS )
+ return SWITCH_STATUS_FALSE;
+
+ 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:
+ */
Added: freeswitch/branches/ctrix/mod_airpe/airpe_if_osx.c
==============================================================================
--- (empty file)
+++ freeswitch/branches/ctrix/mod_airpe/airpe_if_osx.c Mon Jan 12 17:24:44 2009
@@ -0,0 +1,19 @@
+
+#include "mod_airpe.h"
+
+#if defined (MACOSX) || defined(DARWIN)
+
+#error OSX Not yet supported
+
+#endif
+
+/* 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:
+ */
Added: freeswitch/branches/ctrix/mod_airpe/airpe_if_win32.c
==============================================================================
--- (empty file)
+++ freeswitch/branches/ctrix/mod_airpe/airpe_if_win32.c Mon Jan 12 17:24:44 2009
@@ -0,0 +1,19 @@
+
+#include "mod_airpe.h"
+
+#ifdef WIN32
+
+#error WIN32 Not yet supported
+
+#endif
+
+/* 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:
+ */
Added: freeswitch/branches/ctrix/mod_airpe/airpe_if_x11.c
==============================================================================
--- (empty file)
+++ freeswitch/branches/ctrix/mod_airpe/airpe_if_x11.c Mon Jan 12 17:24:44 2009
@@ -0,0 +1,355 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct(a)yahoo.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH mod_airpe.
+ *
+ * The Initial Developer of the Original Code is
+ * Massimo Cetra <devel(a)navynet.it>
+ *
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Thanks to gmaruzz for his work on skypiax (both * and freeswitch).
+ * Some of his code inspired this module
+ *
+ */
+
+#if defined (__GNUC__) && !(defined (MACOSX) || defined(DARWIN) )
+
+#include "mod_airpe.h"
+
+#include <X11/Xlib.h>
+#include <X11/Xlibint.h>
+#include <X11/Xatom.h>
+
+#define X11_MSG_LEN 20
+
+struct skype_window_handler_s {
+ Display *disp;
+ Window win;
+ uint8_t api_connected;
+ int fdesc[2];
+ Window skype_win;
+ int watchdog;
+};
+
+
+
+
+static XErrorHandler old_handler = 0;
+static int xerror = 0;
+
+static int xerrhandler(Display *dpy, XErrorEvent *err)
+{
+ xerror = err->error_code;
+ /* Return 0 so that the error is ignored */
+ return 0;
+}
+
+static void trap_errors()
+{
+ xerror = 0;
+ old_handler = XSetErrorHandler(xerrhandler);
+}
+
+static int untrap_errors()
+{
+ XSetErrorHandler(old_handler);
+ return (xerror != BadValue) && (xerror != BadWindow);
+}
+
+switch_status_t airpe_skype_watchdog_reset(skype_window_handler_t *window) {
+ window->watchdog = 0;
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t airpe_skype_watchdog_increment(skype_window_handler_t *window) {
+ window->watchdog++;
+
+ if ( window->watchdog >= 5 ) {
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+skype_window_handler_t *skype_window_alloc( switch_memory_pool_t *pool) {
+ return switch_core_alloc( pool, sizeof(skype_window_handler_t));
+}
+
+switch_status_t skype_restart( skype_window_handler_t *window, const char *params ) {
+
+ switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
+ "HEY! where is my skype window gone ? Restarting skype for client...\n");
+/*
+
+ TODO AND TO USE
+
+ int fid;
+ const char *args[] = { "skype", "--actiondispatch", params, 0 };
+
+ if((fid = fork()) == 0) {
+ if(execvp("skype", (char *const*)args) == -1) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "airpe client: cannot launch Skype, error %d: %s.\n", errno, strerror(errno) );
+ return SWITCH_STATUS_FALSE;
+ }
+ }
+ else if(fid == -1) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "airpe client: cannot launch Skype.\n");
+ return SWITCH_STATUS_FALSE;
+ }
+*/
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t airpe_skype_send_message(skype_window_handler_t *window, const char *message_P) {
+ Window w_P;
+ Display *disp;
+ Window handle_P;
+ Atom atom1;
+ Atom atom2;
+ unsigned int pos;
+ unsigned int len;
+ XEvent xev;
+ int ok;
+
+ w_P = window->skype_win;
+ disp = window->disp;
+ handle_P = window->win;
+
+ atom1 = XInternAtom(disp, "SKYPECONTROLAPI_MESSAGE_BEGIN", False);
+ atom2 = XInternAtom(disp, "SKYPECONTROLAPI_MESSAGE", False);
+ pos = 0;
+ len = strlen(message_P);
+
+ memset(&xev, 0, sizeof(XEvent));
+ xev.xclient.type = ClientMessage;
+ xev.xclient.message_type = atom1;
+ xev.xclient.display = disp;
+ xev.xclient.window = handle_P;
+ xev.xclient.format = 8;
+
+ trap_errors();
+ do {
+ unsigned int i;
+ for (i = 0; i < 20 && i + pos <= len; ++i)
+ xev.xclient.data.b[i] = message_P[i + pos];
+ XSendEvent(disp, w_P, False, 0, &xev);
+
+ xev.xclient.message_type = atom2;
+ pos += i;
+ } while (pos <= len);
+
+ XSync(disp, False);
+ ok = untrap_errors();
+ if (!ok) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "airpe client X11 error.\n");
+ airpe_skype_avalaible(window);
+ }
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t airpe_skype_avalaible(skype_window_handler_t *window)
+{
+
+ Atom skype_inst;
+ Atom type_ret;
+ int format_ret;
+ unsigned long nitems_ret;
+ unsigned long bytes_after_ret;
+ unsigned char *prop;
+ int status, ok;
+
+ skype_inst = XInternAtom(window->disp, "_SKYPE_INSTANCE", True);
+
+ trap_errors();
+ status = XGetWindowProperty(
+ window->disp,
+ DefaultRootWindow(window->disp),
+ skype_inst,
+ 0,
+ 1,
+ False,
+ XA_WINDOW,
+ &type_ret,
+ &format_ret,
+ &nitems_ret,
+ &bytes_after_ret, &prop);
+
+ ok = untrap_errors();
+ if (!ok) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "airpe client X11 error.\n");
+ airpe_skype_avalaible(window);
+ }
+
+ /* sanity check */
+ if (status != Success || format_ret != 32 || nitems_ret != 1) {
+ window->skype_win = (Window) - 1;
+ return SWITCH_STATUS_FALSE;
+ }
+
+ window->skype_win = *(const unsigned long *) prop & 0xffffffff;
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+
+/*****************************************************************************
+ THREADS
+ *****************************************************************************/
+
+void *SWITCH_THREAD_FUNC airpe_skype_thread(switch_thread_t * thread, void *obj) {
+
+ skype_window_handler_t *skype_window = NULL;
+ airpe_interface_t *airpe = NULL;
+ Display *disp = NULL;
+ Window root = -1;
+ Window win = -1;
+ int xfd;
+
+ assert(obj);
+
+ airpe = obj;
+
+ skype_window = airpe->skype_window;
+ assert(skype_window);
+
+ disp = XOpenDisplay(airpe->X11_display);
+ if (!disp) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "airpe client %s: cannot open display %s\n", airpe->name, airpe->X11_display);
+ return NULL;
+ }
+
+ xfd = XConnectionNumber(disp);
+ fcntl(xfd, F_SETFD, FD_CLOEXEC);
+
+ skype_window->disp = disp;
+
+ if ( airpe_skype_avalaible(skype_window) == SWITCH_STATUS_SUCCESS ) {
+ root = DefaultRootWindow(disp);
+ win = XCreateSimpleWindow(
+ disp,
+ root,
+ 0, 0, 1, 1, 0,
+ BlackPixel(disp, DefaultScreen(disp)),
+ BlackPixel(disp, DefaultScreen(disp))
+ );
+
+ skype_window->win = win;
+
+ if ( airpe_on_connect_messages( airpe, 6 ) != SWITCH_STATUS_SUCCESS ) {
+ switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
+ "airpe client %s. Failed to send handshake messages\n",
+ airpe->name);
+ return NULL;
+ }
+
+ // perform an events loop
+ XEvent an_event;
+ char buf[X11_MSG_LEN + 2] = "";
+ char buffer[SKYPE_MSG_LEN] = "";
+ int i;
+ fd_set rset;
+ int x11_fd;
+ int empty_loops = 0;
+
+ airpe->running = 1;
+ XFlush(disp);
+ x11_fd = ConnectionNumber(disp);
+
+ while ( airpe->running ) {
+ FD_ZERO(&rset);
+ FD_SET( x11_fd, &rset);
+
+ struct timeval timeout;
+ int ret;
+
+ timeout.tv_usec = 10 * 1000;
+ ret = select(x11_fd+1, &rset, 0, 0, &timeout);
+
+ if ( !airpe->running ) /* Quick way to skip the loop when we are signaled to exit. */
+ break;
+
+ if ( ret <=0 ) {
+ empty_loops ++;
+ if ( empty_loops >= 250 ) {
+ airpe_cmd_write(airpe, "PING");
+ airpe_skype_watchdog_increment(skype_window);
+ empty_loops = 0;
+ }
+ continue;
+ }
+
+ airpe_skype_watchdog_reset(skype_window);
+
+ /* Process all the pending messages queued (not only one) */
+ while ( XPending(disp) )
+ {
+ XNextEvent(disp, &an_event);
+
+ switch (an_event.type)
+ {
+ case ClientMessage:
+ if (an_event.xclient.format != 8)
+ break;
+
+ for (i = 0; i < X11_MSG_LEN && an_event.xclient.data.b[i] != '\0'; ++i) {
+ buf[i] = an_event.xclient.data.b[i];
+ }
+ buf[i] = '\0';
+
+ strcat(buffer, buf);
+
+ if (i < X11_MSG_LEN) {
+ unsigned int howmany;
+ howmany = strlen(buffer) + 1;
+ airpe_manage_skype_msg( airpe, buffer);
+ memset(&buffer, 0, sizeof(buffer));
+ }
+ break;
+ default:
+ if ( airpe->debug )
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "airpe client %s: unknown event\n", airpe->name);
+ break;
+ }
+ }
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "airpe client %s: exiting thread\n", airpe->name);
+
+ /* Hangup our call, if we have one */
+ airpe_explicit_hangup(airpe);
+
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "airpe client %s: skype not running on display %s\n", airpe->name, airpe->X11_display);
+ }
+
+ return NULL;
+}
+
+#endif
+
+/* 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:
+ */
Added: freeswitch/branches/ctrix/mod_airpe/config/airpe.conf.xml
==============================================================================
--- (empty file)
+++ freeswitch/branches/ctrix/mod_airpe/config/airpe.conf.xml Mon Jan 12 17:24:44 2009
@@ -0,0 +1,36 @@
+<configuration name="airpe.conf" description="Airpe Configuration">
+ <globals>
+ <param name="audio-tcp-port_start" value="21000"/>
+
+ <!-- Those params are used for all clients if not explicitly set for each one -->
+ <param name="context" value="public"/>
+ <param name="dialplan" value="XML"/>
+ <param name="destination" value="5000"/>
+ </globals>
+
+ <!-- one entry here per airpe client -->
+ <clients>
+ <client name="airpe1">
+ <!-- Print out as notices the client messages -->
+ <param name="debug" value="1"/>
+
+ <!-- Where our calls will land -->
+ <param name="dialplan" value="XML"/>
+ <param name="context" value="default"/>
+ <param name="destination" value="4321"/>
+
+ <!-- Linux only -->
+ <param name="X11-display" value=":101"/>
+
+ <!-- Not used yet -->
+ <param name="cid-name" value="Skype 1"/>
+ <param name="cid-num" value="0000001"/>
+
+ <!-- Not used... maybe should be removed.
+ The purpose is restarting the client with those credentials -->
+ <param name="skype-user" value="username"/>
+ <param name="skype-password" value="password"/>
+ </client>
+ </clients>
+
+</configuration>
Added: freeswitch/branches/ctrix/mod_airpe/mod_airpe.c
==============================================================================
--- (empty file)
+++ freeswitch/branches/ctrix/mod_airpe/mod_airpe.c Mon Jan 12 17:24:44 2009
@@ -0,0 +1,868 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct(a)yahoo.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH mod_airpe.
+ *
+ * The Initial Developer of the Original Code is
+ * Massimo Cetra <devel(a)navynet.it>
+ *
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Thanks to gmaruzz for his work on skypiax (both * and freeswitch).
+ * Some of his code inspired this module
+ *
+ */
+
+#include "mod_airpe.h"
+
+/*****************************************************************************
+ MODULE PRIVATE STRUCTS && FUNCTIONS
+ *****************************************************************************/
+
+static switch_endpoint_interface_t *airpe_endpoint_interface;
+
+static struct {
+ char *dialplan;
+ char *context;
+ char *destination;
+ int audio_tcp_port_start;
+
+ switch_mutex_t *mutex;
+ switch_hash_t *interfaces_hash;
+ int last_port_used;
+} globals;
+
+static switch_memory_pool_t *airpe_module_pool = NULL;
+
+
+airpe_interface_t *airpe_find_interface( const char *name) {
+ return switch_core_hash_find(globals.interfaces_hash, name);
+}
+
+
+/*****************************************************************************
+ TECH STUFF
+ *****************************************************************************/
+
+static switch_status_t airpe_codec_init(private_object_t * tech_pvt, int sample_rate, int codec_ms) {
+ airpe_interface_t *airpe = NULL;
+
+ if ( switch_core_codec_init(&tech_pvt->read_codec, "L16", NULL, sample_rate, codec_ms, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, NULL) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "airpe client: %s - Cannot init read codec.\n", airpe->name);
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if ( switch_core_codec_init(&tech_pvt->write_codec, "L16", NULL, sample_rate, codec_ms, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, NULL) != SWITCH_STATUS_SUCCESS ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "airpe client: %s - Cannot init write codec.\n", airpe->name);
+ switch_core_codec_destroy(&tech_pvt->read_codec);
+ return SWITCH_STATUS_FALSE;
+ }
+
+ tech_pvt->read_frame.rate = sample_rate;
+ tech_pvt->read_frame.codec = &tech_pvt->read_codec;
+
+ switch_core_session_set_read_codec(tech_pvt->session, &tech_pvt->read_codec);
+ switch_core_session_set_write_codec(tech_pvt->session, &tech_pvt->write_codec);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t airpe_tech_init( private_object_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;
+ return airpe_codec_init(tech_pvt, CODEC_SAMPLE_RATE, CODEC_INTERVAL_MS);
+}
+
+static switch_socket_t *airpe_socket_create( const char *host, int port ) {
+ switch_status_t rv;
+ switch_socket_t *new_sock = NULL;
+ switch_sockaddr_t *sa;
+
+ rv = switch_sockaddr_info_get(&sa, host, AF_INET, port, 0, airpe_module_pool);
+ if ( rv != SWITCH_STATUS_SUCCESS ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Creation Error! (1)\n");
+ return NULL;
+ }
+
+ rv = switch_socket_create(&new_sock, AF_INET, SOCK_STREAM, SWITCH_PROTO_TCP, airpe_module_pool);
+ if ( rv != SWITCH_STATUS_SUCCESS ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Creation Error! (2)\n");
+ return NULL;
+ }
+
+ rv = switch_socket_opt_set(new_sock, SWITCH_SO_REUSEADDR, 1);
+ if ( rv != SWITCH_STATUS_SUCCESS ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Creation Error! (3)\n");
+ return NULL;
+ }
+
+ rv = switch_socket_opt_set(new_sock, SWITCH_SO_NONBLOCK, 1);
+ if ( rv != SWITCH_STATUS_SUCCESS ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Creation Error! (3)\n");
+ return NULL;
+ }
+
+ rv = switch_socket_bind(new_sock, sa);
+ if ( rv != SWITCH_STATUS_SUCCESS ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Creation Error! (4)\n");
+ return NULL;
+ }
+
+ rv = switch_socket_listen(new_sock, 5);
+ if ( rv != SWITCH_STATUS_SUCCESS ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Creation Error! (5)\n");
+ return NULL;
+ }
+
+ return new_sock;
+}
+
+static int fetch_next_port(void) {
+ int port = 0;
+
+ if ( !globals.last_port_used )
+ globals.last_port_used = globals.audio_tcp_port_start;
+
+ switch_mutex_lock(globals.mutex);
+ port = globals.last_port_used;
+ globals.last_port_used++;
+ switch_mutex_unlock(globals.mutex);
+
+ return port;
+}
+
+static switch_status_t airpe_audio_sockets_create( airpe_interface_t *airpe ) {
+ switch_socket_t *new_sock;
+ int port;
+
+ new_sock = NULL;
+ while ( !new_sock ) {
+ port = fetch_next_port();
+ if ( airpe->debug )
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Assigning in port %d for client %s\n", port, airpe->name);
+ new_sock = airpe_socket_create("127.0.0.1", port);
+ if ( new_sock ) {
+ airpe->audio_in_socket = new_sock;
+ airpe->audio_in_port = port;
+ }
+ }
+
+ new_sock = NULL;
+ while ( !new_sock ) {
+ port = fetch_next_port();
+ if ( airpe->debug )
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Assigning out port %d for client %s\n", port, airpe->name);
+ new_sock = airpe_socket_create("127.0.0.1", port);
+ if ( new_sock ) {
+ airpe->audio_out_socket = new_sock;
+ airpe->audio_out_port = port;
+ }
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+static switch_status_t airpe_start_client(airpe_interface_t *airpe) {
+
+ switch_threadattr_t *attr_skype = NULL;
+
+ airpe->user_status = USER_STATUS_UNKNOWN;
+ airpe->conn_status = CONN_STATUS_UNKNOWN;
+ airpe->call_status = CALL_STATUS_UNKNOWN;
+
+ airpe_audio_sockets_create(airpe);
+
+ switch_threadattr_create(&attr_skype, airpe_module_pool);
+ //switch_threadattr_detach_set(attr_skype, 1);
+ switch_threadattr_stacksize_set(attr_skype, SWITCH_THREAD_STACKSIZE);
+
+ switch_thread_create(&airpe->airpe_thread_skype,
+ attr_skype,
+ airpe_skype_thread,
+ airpe,
+ airpe_module_pool);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t airpe_stop_client(airpe_interface_t *airpe) {
+
+ if ( airpe->audio_in_socket ) {
+ if ( airpe->debug )
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Shutting down socket on port %d for client %s\n", airpe->audio_in_port, airpe->name);
+ airpe->audio_in_port = 0;
+ switch_socket_shutdown(airpe->audio_in_socket, SWITCH_SHUTDOWN_READWRITE);
+ switch_socket_close(airpe->audio_in_socket);
+ }
+
+ if ( airpe->audio_out_socket ) {
+ if ( airpe->debug )
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Shutting down socket on port %d for client %s\n", airpe->audio_out_port, airpe->name);
+ airpe->audio_out_port = 0;
+ switch_socket_shutdown(airpe->audio_out_socket, SWITCH_SHUTDOWN_READWRITE);
+ switch_socket_close(airpe->audio_out_socket);
+ }
+
+ airpe_set_version(airpe, NULL);
+ airpe_set_mood_text(airpe, NULL);
+ airpe_set_partner_displayname(airpe, NULL);
+ airpe_set_partner_handle(airpe, NULL);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_core_session_t *airpe_request_session( switch_memory_pool_t **pool ) {
+ /* I prefer not to expose airpe_endpoint_interface out of this file. */
+ return switch_core_session_request(airpe_endpoint_interface, pool);
+}
+
+
+/*****************************************************************************
+ CHANNEL STATE HANDLERS
+ *****************************************************************************/
+
+static switch_status_t channel_on_init(switch_core_session_t * session)
+{
+ switch_channel_t *channel;
+ private_object_t *tech_pvt = NULL;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt);
+ assert(tech_pvt->airpe);
+
+ tech_pvt->airpe->tech_pvt = tech_pvt;
+
+ if ( switch_test_flag(tech_pvt, TFLAG_OUTBOUND) ) {
+ airpe_originate(tech_pvt->airpe, tech_pvt->destination );
+ // TODO if fail switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
+ }
+
+ if ( switch_test_flag(tech_pvt, TFLAG_INBOUND) ) {
+ char buf[SKYPE_MSG_LEN];
+ snprintf(buf, sizeof(buf), "ALTER CALL %d SET_INPUT PORT=\"%d\"", tech_pvt->airpe->active_call_id, tech_pvt->airpe->audio_in_port);
+ airpe_cmd_write(tech_pvt->airpe, buf);
+ snprintf(buf, sizeof(buf), "ALTER CALL %d SET_OUTPUT PORT=\"%d\"", tech_pvt->airpe->active_call_id, tech_pvt->airpe->audio_out_port);
+ airpe_cmd_write(tech_pvt->airpe, buf);
+
+ switch_channel_set_state(channel, CS_ROUTING);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_on_routing(switch_core_session_t * session) {
+ char buf[SKYPE_MSG_LEN];
+ switch_channel_t *channel = NULL;
+ private_object_t *tech_pvt = NULL;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt);
+
+ if ( switch_test_flag(tech_pvt, TFLAG_INBOUND) ) {
+ snprintf(buf, sizeof(buf), "ALTER CALL %d ANSWER", tech_pvt->airpe->active_call_id);
+ airpe_cmd_write(tech_pvt->airpe, buf);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_on_execute(switch_core_session_t * session) {
+ switch_channel_t *channel = NULL;
+ private_object_t *tech_pvt = NULL;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_on_hangup(switch_core_session_t * session)
+{
+ switch_channel_t *channel = NULL;
+ private_object_t *tech_pvt = NULL;
+ airpe_interface_t *airpe = NULL;
+ char msg[SKYPE_MSG_LEN];
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt);
+
+ airpe = tech_pvt->airpe;
+ assert(airpe);
+
+ if ( airpe->active_call_id ) {
+ snprintf(msg, sizeof(msg), "ALTER CALL %d HANGUP", airpe->active_call_id);
+ airpe_cmd_write(airpe, msg);
+// airpe->active_call_id = 0;
+// airpe->tech_pvt = NULL;
+ }
+
+ airpe_hangup( tech_pvt );
+
+ if (tech_pvt->read_codec.implementation) {
+ switch_core_codec_destroy(&tech_pvt->read_codec);
+ }
+
+ if (tech_pvt->write_codec.implementation) {
+ switch_core_codec_destroy(&tech_pvt->write_codec);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_on_exchange_media(switch_core_session_t * session) {
+ return SWITCH_STATUS_SUCCESS;
+}
+
+/*****************************************************************************
+ CHANNEL IO INTERFACE / ROUTINES
+ *****************************************************************************/
+static switch_call_cause_t channel_outgoing_channel(
+ switch_core_session_t *session,
+ switch_event_t *var_event,
+ switch_caller_profile_t *outbound_profile,
+ switch_core_session_t **new_session,
+ switch_memory_pool_t **pool,
+ switch_originate_flag_t flags)
+{
+ switch_caller_profile_t *caller_profile = NULL;
+ private_object_t *tech_pvt = NULL;
+ switch_channel_t *channel = NULL;
+
+ assert(outbound_profile);
+
+ /* New session creation */
+ *new_session = airpe_request_session(pool);
+ if ( *new_session )
+ {
+ char *chan_interface = NULL;
+ char *chan_destination = NULL;
+
+ switch_core_session_add_stream(*new_session, NULL);
+
+ tech_pvt = (private_object_t *) switch_core_session_alloc(*new_session, sizeof(private_object_t));
+
+ if ( tech_pvt ) {
+ channel = switch_core_session_get_channel(*new_session);
+ if ( airpe_tech_init( tech_pvt, *new_session ) != SWITCH_STATUS_SUCCESS ) {
+ switch_core_session_destroy(new_session);
+ return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+ }
+ } else {
+ switch_core_session_destroy(new_session);
+ return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+ }
+
+
+ chan_interface = switch_core_session_strdup( *new_session, outbound_profile->destination_number);
+ if (( chan_destination = strchr(chan_interface, '/'))) {
+ *chan_destination++ = '\0';
+ }
+ if ( !chan_interface || !chan_destination ) {
+ switch_core_session_destroy(new_session);
+ return SWITCH_CAUSE_INVALID_NUMBER_FORMAT;
+ }
+
+ if ( (tech_pvt->airpe = airpe_find_interface(chan_interface))==NULL ) {
+ switch_core_session_destroy(new_session);
+ return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+ }
+ tech_pvt->destination = chan_destination;
+
+ if ( tech_pvt->airpe->active_call_id != 0 ) {
+ /* We're busy, man! */
+ switch_core_session_destroy(new_session);
+ return SWITCH_CAUSE_REQUESTED_CHAN_UNAVAIL;
+ }
+
+ if (outbound_profile) {
+ char name[128];
+ snprintf(name, sizeof(name), "airpe/%s", outbound_profile->destination_number);
+ switch_channel_set_name(channel, name);
+ caller_profile = switch_caller_profile_clone(*new_session, outbound_profile);
+ switch_channel_set_caller_profile(channel, caller_profile);
+ tech_pvt->caller_profile = caller_profile;
+ }
+ else
+ {
+ 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;
+ }
+ else
+ {
+ return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+ }
+}
+
+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_object_t *tech_pvt = NULL;
+ switch_byte_t *data;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt);
+
+ tech_pvt->read_frame.flags = SFF_NONE;
+ *frame = NULL;
+
+ if ( airpe_audio_read(tech_pvt) != SWITCH_STATUS_SUCCESS) {
+ ADEBUG("airpe_audio_read ERROR\n");
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (!tech_pvt->read_frame.datalen) {
+ goto cng;
+ }
+
+ *frame = &tech_pvt->read_frame;
+
+ return SWITCH_STATUS_SUCCESS;
+
+cng:
+ data = (switch_byte_t *) tech_pvt->read_frame.data;
+ data[0] = 65;
+ data[1] = 0;
+ tech_pvt->read_frame.datalen = 2;
+ tech_pvt->read_frame.flags = SFF_CNG;
+ *frame = &tech_pvt->read_frame;
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_write_frame(switch_core_session_t * session,
+ switch_frame_t * frame,
+ switch_io_flag_t flags,
+ int stream_id)
+{
+ switch_channel_t *channel = NULL;
+ private_object_t *tech_pvt = NULL;
+ airpe_interface_t *airpe = NULL;
+ switch_status_t rv;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt);
+
+ if ( !tech_pvt->airpe ) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ airpe = tech_pvt->airpe;
+
+ rv = airpe_audio_write(tech_pvt, frame);
+ return rv;
+}
+
+static switch_status_t channel_kill_channel(switch_core_session_t * session, int sig)
+{
+ switch_channel_t *channel = NULL;
+ private_object_t *tech_pvt = NULL;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt);
+
+ switch (sig) {
+ case SWITCH_SIG_KILL:
+ break;
+ case SWITCH_SIG_BREAK:
+ break;
+ default:
+ //TODO Log unhandled signal
+ break;
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_send_dtmf(switch_core_session_t * session, const switch_dtmf_t * dtmf) {
+ private_object_t *tech_pvt = switch_core_session_get_private(session);
+ airpe_interface_t *airpe;
+ char buf[SKYPE_MSG_LEN];
+
+ switch_assert(tech_pvt);
+
+ airpe = tech_pvt->airpe;
+
+ if ( airpe->active_call_id ) {
+ snprintf(buf, sizeof(buf), "SET CALL %d DTMF %c", airpe->active_call_id, dtmf->digit);
+ airpe_cmd_write(airpe, buf);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_receive_message(switch_core_session_t * session, switch_core_session_message_t * msg)
+{
+ switch_channel_t *channel;
+ private_object_t *tech_pvt;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel);
+
+ tech_pvt = (private_object_t *) switch_core_session_get_private(session);
+ assert(tech_pvt);
+
+ switch (msg->message_id) {
+ case SWITCH_MESSAGE_INDICATE_ANSWER:
+ ADEBUG("received message indicate answer...\n");
+/*
+ //switch_answer_channel(session);
+ char buf[SKYPE_MSG_LEN];
+ snprintf(buf, sizeof(buf), "ALTER CALL %d ANSWER", tech_pvt->airpe->active_call_id );
+ airpe_cmd_write(tech_pvt->airpe, buf);
+*/
+ break;
+ case SWITCH_MESSAGE_INDICATE_UNBRIDGE:
+ ADEBUG("received message indicate unbridge...\n");
+ break;
+ case SWITCH_MESSAGE_INDICATE_TRANSCODING_NECESSARY:
+ ADEBUG("received message indicate transcode necessary...\n");
+ break;
+ case SWITCH_MESSAGE_INDICATE_AUDIO_SYNC:
+ ADEBUG("received message indicate audio sync...\n");
+ break;
+ case SWITCH_MESSAGE_INDICATE_TRANSFER:
+ ADEBUG("received message indicate transfer...\n");
+ break;
+ default:
+ ADEBUG("Unmanaged received message... %d\n", msg->message_id);
+ break;
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_receive_event(switch_core_session_t * session, switch_event_t * event)
+{
+ char *body = NULL;
+ switch_channel_t *channel;
+ private_object_t *tech_pvt;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel);
+
+ tech_pvt = (private_object_t *) switch_core_session_get_private(session);
+ assert(tech_pvt);
+
+ body = switch_event_get_body(event);
+
+ if (!body) {
+ body = "";
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+/*****************************************************************************
+ CONFIGURATION
+ *****************************************************************************/
+
+static switch_status_t load_config(void) {
+ switch_xml_t cfg,
+ xml,
+ global_settings,
+ param,
+ clients,
+ client;
+ switch_memory_pool_t *pool;
+
+ pool = airpe_module_pool;
+
+ if (!(xml = switch_xml_open_cfg("airpe.conf", &cfg, NULL))) {
+ return SWITCH_STATUS_TERM;
+ }
+
+ if ( (global_settings = switch_xml_child(cfg, "globals") ) ) {
+ for (param = switch_xml_child(global_settings, "param"); param; param = param->next) {
+ char *var = (char *) switch_xml_attr_soft(param, "name");
+ char *val = (char *) switch_xml_attr_soft(param, "value");
+
+ if (!strcmp(var, "dialplan")) {
+ globals.dialplan = switch_core_strdup(pool, val);
+ } else if (!strcmp(var, "context")) {
+ globals.context = switch_core_strdup(pool, val);
+ } else if (!strcmp(var, "destination")) {
+ globals.destination = switch_core_strdup(pool, val);
+ } else if (!strcmp(var, "audio-tcp-port_start")) {
+ globals.audio_tcp_port_start = atoi(val);
+ }
+ }
+ }
+
+ if ( globals.audio_tcp_port_start <= 0 ) {
+ globals.audio_tcp_port_start = 21000;
+ }
+
+ if ( !globals.dialplan )
+ globals.dialplan = switch_core_strdup(pool, "XML");
+ if ( !globals.context )
+ globals.context = switch_core_strdup(pool, "default");
+ if ( !globals.destination )
+ globals.destination = switch_core_strdup(pool, "4321");
+
+ if ((clients = switch_xml_child(cfg, "clients"))) {
+
+ for (client = switch_xml_child(clients, "client"); client; client = client->next)
+ {
+ char *name = (char *) switch_xml_attr(client, "name");
+ char *context = NULL;
+ char *dialplan = NULL;
+ char *destination = NULL;
+ char *X11_display = NULL;
+ char *skype_user = NULL;
+ char *skype_password= NULL;
+ char *cid_name = NULL;
+ char *cid_num = NULL;
+ int debug = 0;
+
+ airpe_interface_t *newconf = NULL;
+
+ if (!name) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No name attribute. Skipping unnamed client.\n");
+ continue;
+ }
+
+ if ( (newconf = switch_core_hash_find(globals.interfaces_hash, name)) ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Duplicated client %s. Skipping\n", name);
+ continue;
+ }
+
+ for (param = switch_xml_child(client, "param"); param; param = param->next) {
+ char *var = (char *) switch_xml_attr_soft(param, "name");
+ char *val = (char *) switch_xml_attr_soft(param, "value");
+
+ if (!strcasecmp(var, "debug")) {
+ debug = switch_true(val) ? 1 : 0;
+ } else if (!strcasecmp(var, "context")) {
+ context = val;
+ } else if (!strcasecmp(var, "dialplan")) {
+ dialplan = val;
+ } else if (!strcasecmp(var, "destination")) {
+ destination = val;
+ } else if (!strcasecmp(var, "skype-user")) {
+ skype_user = val;
+ } else if (!strcasecmp(var, "skype-password")) {
+ skype_password = val;
+ } else if (!strcasecmp(var, "X11-display")) {
+ X11_display = val;
+ } else if (!strcasecmp(var, "cid-name")) {
+ cid_name = val;
+ } else if (!strcasecmp(var, "cid-num")) {
+ cid_num = val;
+ }
+ else
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unknown config param %s\n", var);
+ }
+ if (!skype_user) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No skype-user param for client %s. Skipping\n", name);
+ continue;
+ }
+ if (!skype_password) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No skype-password param for client %s. Skipping\n", name);
+ continue;
+ }
+ if (!X11_display) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No X11-display param for client %s. Skipping\n", name);
+ continue;
+ }
+
+ if ( !dialplan )
+ dialplan = globals.dialplan;
+ if ( !context )
+ context = globals.context;
+ if ( !destination )
+ destination = globals.destination;
+
+ newconf = (airpe_interface_t *) switch_core_alloc( pool, sizeof(airpe_interface_t) );
+
+ if ( newconf ) {
+ switch_status_t status;
+
+ memset(newconf, 0, sizeof(airpe_interface_t));
+
+ newconf->name = switch_core_strdup(pool, name);
+ newconf->dialplan = switch_core_strdup(pool, dialplan);
+ newconf->context = switch_core_strdup(pool, context);
+ newconf->destination = switch_core_strdup(pool, destination);
+ newconf->skype_user = switch_core_strdup(pool, skype_user);
+ newconf->skype_password = switch_core_strdup(pool, skype_password);
+ newconf->X11_display = switch_core_strdup(pool, X11_display);
+ newconf->audio_in_port = 0;
+ newconf->audio_in_port = 0;
+ newconf->debug = debug;
+
+ newconf->skype_window = skype_window_alloc(pool);
+
+ if ( newconf->skype_window ) {
+ status = airpe_start_client(newconf);
+
+ if ( status == SWITCH_STATUS_SUCCESS ) {
+ switch_core_hash_insert(globals.interfaces_hash, name, newconf);
+ }
+ else {
+ // LOG OUR ERROR
+ }
+ }
+ else {
+ // LOG OUR ERROR
+ }
+
+ }
+ else {
+ //TODO LOG ERROR ABOUT CREATING INTERFACE
+ }
+ }
+
+ }
+
+ switch_xml_free(xml);
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+/*****************************************************************************
+ MODULE INITIALIZATION FUNCTIONS
+ *****************************************************************************/
+
+static switch_state_handler_table_t airpe_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 */ NULL
+};
+
+static switch_io_routines_t airpe_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
+};
+
+SWITCH_MODULE_LOAD_FUNCTION(mod_airpe_load);
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_airpe_shutdown);
+SWITCH_MODULE_DEFINITION(mod_airpe, mod_airpe_load, mod_airpe_shutdown, NULL);
+
+SWITCH_MODULE_LOAD_FUNCTION(mod_airpe_load)
+{
+ airpe_module_pool = pool;
+
+ memset(&globals, 0, sizeof(globals));
+
+ switch_core_hash_init(&globals.interfaces_hash, pool);
+ switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, pool);
+
+ load_config();
+
+ *module_interface = switch_loadable_module_create_module_interface(pool, modname);
+
+ airpe_endpoint_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE);
+
+ airpe_endpoint_interface->interface_name = "airpe";
+ airpe_endpoint_interface->io_routines = &airpe_io_routines;
+ airpe_endpoint_interface->state_handler = &airpe_state_handlers;
+
+ airpe_register_api( &*module_interface );
+ airpe_register_apps( &*module_interface );
+
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_airpe_shutdown)
+{
+ switch_memory_pool_t *pool;
+ airpe_interface_t *airpe;
+ switch_hash_index_t *hi;
+ void *val;
+
+ pool = airpe_module_pool;
+
+ for (hi = switch_hash_first(NULL, globals.interfaces_hash); hi; hi = switch_hash_next(hi)) {
+ switch_hash_this(hi, NULL, NULL, &val);
+ airpe = ( airpe_interface_t *) val;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Shutting down airpe client: %s\n", airpe->name);
+ airpe->running = 0;
+ /* Wake up the socket */
+ airpe_cmd_write(airpe, "PING");
+ airpe_stop_client(airpe);
+ /*
+ we won't delete the hash element. we're going to destroy the whole pool
+ switch_core_hash_delete(globals.interfaces_hash, airpe->name);
+ */
+ }
+ switch_yield(500000);
+
+ /* TODO... should we check that all interfaces has been switched off ? */
+
+ switch_core_hash_destroy(&globals.interfaces_hash);
+ switch_core_destroy_memory_pool(&pool);
+ return SWITCH_STATUS_UNLOAD;
+}
+
+/* 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:
+ */
Added: freeswitch/branches/ctrix/mod_airpe/mod_airpe.h
==============================================================================
--- (empty file)
+++ freeswitch/branches/ctrix/mod_airpe/mod_airpe.h Mon Jan 12 17:24:44 2009
@@ -0,0 +1,235 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct(a)yahoo.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH mod_airpe.
+ *
+ * The Initial Developer of the Original Code is
+ * Massimo Cetra <devel(a)navynet.it>
+ *
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Thanks to gmaruzz for his work on skypiax (both * and freeswitch).
+ * Some of his code inspired this module
+ *
+ */
+
+#include <switch.h>
+#include <switch_version.h>
+
+#define MODNAME "airpe"
+
+#define SKYPE_MSG_LEN 1024
+
+#define CODEC_SAMPLE_RATE 16000
+#define CODEC_INTERVAL_MS 20
+#define FRAMES_PER_SECOND 1000 / CODEC_INTERVAL_MS
+#define SAMPLES_PER_FRAME CODEC_SAMPLE_RATE / FRAMES_PER_SECOND
+
+#define ADEBUG(...) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, __VA_ARGS__ );
+
+typedef enum {
+ CONN_STATUS_UNKNOWN,
+ CONN_STATUS_OFFLINE,
+ CONN_STATUS_CONNECTING,
+ CONN_STATUS_PAUSING,
+ CONN_STATUS_ONLINE,
+} CONN_STATUS;
+
+typedef enum {
+ USER_STATUS_UNKNOWN,
+ USER_STATUS_ONLINE,
+ USER_STATUS_OFFLINE,
+ USER_STATUS_SKYPEME,
+ USER_STATUS_AWAY,
+ USER_STATUS_NA,
+ USER_STATUS_DND,
+ USER_STATUS_INVISIBLE,
+ USER_STATUS_LOGGEDOUT
+} USER_STATUS;
+
+typedef enum {
+ CALL_STATUS_UNKNOWN,
+ CALL_STATUS_UNPLACED,
+ CALL_STATUS_ROUTING,
+ CALL_STATUS_EARLYMEDIA,
+ CALL_STATUS_FAILED,
+ CALL_STATUS_RINGING,
+ CALL_STATUS_INPROGRESS,
+ CALL_STATUS_ONHOLD,
+ CALL_STATUS_LOCALHOLD,
+ CALL_STATUS_REMOTEHOLD,
+ CALL_STATUS_FINISHED,
+ CALL_STATUS_MISSED,
+ CALL_STATUS_REFUSED,
+ CALL_STATUS_BUSY,
+ CALL_STATUS_CANCELLED,
+ CALL_STATUS_TRANSFERRING, /* Protocol 7 */
+ CALL_STATUS_TRANSFERRED, /* Protocol 7 */
+
+ CALL_STATUS_VM_BUFFERING_GREETING,
+ CALL_STATUS_VM_PLAYING_GREETING,
+ CALL_STATUS_VM_RECORDING,
+ CALL_STATUS_VM_UPLOADING,
+ CALL_STATUS_VM_SENT,
+ CALL_STATUS_VM_CANCELLED ,
+ CALL_STATUS_VM_FAILED,
+ CALL_STATUS_WAITING_REDIAL_COMMAND,
+ CALL_STATUS_REDIAL_PENDING, /* Protocol 8 */
+
+} CALL_STATUS;
+
+typedef enum {
+ FAILURE_CODE_MISC = 1,
+ FAILURE_CODE_BAD_DESTINATION_NUM = 2,
+ FAILURE_CODE_USER_OFFLINE = 3,
+ FAILURE_CODE_NO_PROXY_FOUND = 4,
+ FAILURE_CODE_SESSION_TERMINATED = 5,
+ FAILURE_CODE_NO_CODEC_FOUND = 6,
+ FAILURE_CODE_LOCAL_SOUND_ERR = 7,
+ FAILURE_CODE_REMOTE_SOUND_ERR = 8,
+ FAILURE_CODE_CALL_BLOCKED = 9,
+ FAILURE_CODE_RECIPIENT_NOT_FRIEND = 10,
+ FAILURE_CODE_CALL_UNAUTHORIZED = 11,
+ FAILURE_CODE_SOUND_REC_ERR = 12,
+} FAILURE_CODES;
+
+
+typedef enum {
+ TFLAG_INBOUND = (1 << 1),
+ TFLAG_OUTBOUND = (1 << 2),
+/*
+ TFLAG_IO = (1 << 0),
+ TFLAG_DTMF = (1 << 3),
+ TFLAG_VOICE = (1 << 4),
+ TFLAG_HANGUP = (1 << 5),
+ TFLAG_LINEAR = (1 << 6),
+ TFLAG_CODEC = (1 << 7),
+ TFLAG_BREAK = (1 << 8),
+ TFLAG_ANSWER = (1 << 9)
+*/
+} TFLAGS;
+
+typedef struct skype_window_handler_s skype_window_handler_t;
+
+typedef struct airpe_interface_s airpe_interface_t;
+typedef struct private_object_s private_object_t;
+
+struct airpe_interface_s {
+ char *name;
+ int debug;
+ char *dialplan;
+ char *context;
+ char *destination;
+ char *X11_display;
+ char *skype_user;
+ char *skype_password;
+
+ int audio_in_port;
+ int audio_out_port;
+ switch_socket_t *audio_in_socket;
+ switch_socket_t *audio_out_socket;
+ switch_socket_t *audio_in_active_socket;
+ switch_socket_t *audio_out_active_socket;
+
+ switch_thread_t *airpe_thread_skype;
+ skype_window_handler_t *skype_window;
+
+ int protocol;
+ USER_STATUS user_status;
+ CALL_STATUS call_status;
+ CONN_STATUS conn_status;
+
+ char *skype_version;
+ char *mood_text;
+ int active_call_id;
+ int last_fail_reason;
+ int running;
+ private_object_t *tech_pvt;
+ char *partner_displayname;
+ char *partner_handle;
+};
+
+struct private_object_s {
+ unsigned int flags;
+ switch_mutex_t *flag_mutex;
+ switch_mutex_t *mutex;
+
+ airpe_interface_t *airpe;
+ switch_core_session_t *session;
+ switch_caller_profile_t *caller_profile;
+ char *destination;
+
+ switch_codec_t read_codec;
+ switch_codec_t write_codec;
+ switch_frame_t read_frame;
+ uint8_t databuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
+};
+
+
+/* CORE */
+airpe_interface_t *airpe_find_interface( const char *name);
+switch_core_session_t *airpe_request_session( switch_memory_pool_t **pool );
+switch_status_t airpe_tech_init( private_object_t * tech_pvt, switch_core_session_t * session );
+
+/* API */
+switch_status_t airpe_register_api( switch_loadable_module_interface_t **module_interface );
+
+/* APPS */
+switch_status_t airpe_register_apps( switch_loadable_module_interface_t **module_interface );
+
+/* INTERFACE - COMMON FUNCTIONS */
+const char *skype_user_status_string(USER_STATUS st);
+USER_STATUS skype_user_status(const char *str);
+const char *skype_conn_status_string(CONN_STATUS st);
+CONN_STATUS skype_conn_status(const char *str);
+
+switch_status_t airpe_set_version(airpe_interface_t *airpe, char *string);
+switch_status_t airpe_set_mood_text(airpe_interface_t *airpe, char *string);
+switch_status_t airpe_set_partner_displayname(airpe_interface_t *airpe, char *string);
+switch_status_t airpe_set_partner_handle(airpe_interface_t *airpe, char *string);
+
+switch_status_t airpe_hangup( private_object_t *pvt );
+switch_status_t airpe_audio_read( private_object_t *pvt );
+switch_status_t airpe_audio_write( private_object_t *pvt, switch_frame_t *frame );
+
+switch_status_t airpe_cmd_write(airpe_interface_t *p, char *msg);
+switch_status_t airpe_originate(airpe_interface_t *p, char *dest);
+switch_status_t airpe_explicit_hangup(airpe_interface_t *airpe);
+switch_status_t airpe_manage_skype_msg( airpe_interface_t *airpe, const char *msg );
+
+switch_status_t airpe_on_connect_messages( airpe_interface_t *airpe, int protocol );
+
+/* INTERFACE - PLATFORM DEPENDANT FUNCTIONS */
+switch_status_t airpe_skype_watchdog_reset(skype_window_handler_t *window);
+switch_status_t airpe_skype_watchdog_increment(skype_window_handler_t *window);
+skype_window_handler_t *skype_window_alloc( switch_memory_pool_t *pool);
+switch_status_t airpe_skype_avalaible(skype_window_handler_t *window);
+switch_status_t skype_restart( skype_window_handler_t *airpe, const char *params );
+switch_status_t airpe_skype_send_message(skype_window_handler_t *window, const char *message_P);
+void *SWITCH_THREAD_FUNC airpe_skype_thread(switch_thread_t * thread, void *obj);
+
+/* 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:
+ */
1
0
[commit] r11144 - freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax
by FreeSWITCH SVN 12 Jan '09
by FreeSWITCH SVN 12 Jan '09
12 Jan '09
Author: gmaruzz
Date: Mon Jan 12 13:03:06 2009
New Revision: 11144
Log:
docs
Modified:
freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/README
Modified: freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/README
==============================================================================
--- freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/README (original)
+++ freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/README Mon Jan 12 13:03:06 2009
@@ -17,7 +17,9 @@
If your server's Skype client(s) has got the Skype credits, Skypiax works for SkypeOut calls too.
-You can use it from the dialplan, eg with the provided modified "default.xml" dialplan, you can call "sip:skype/remote_skypename__OR__skypeout_phonenumber" for calling via the Skype network from a SIP softphone to remote_skypename or to a phone number via SkypeOut, or you can call the "2908" extension from any phone to be bridged to the Skype Test Call).
+You can use it from the dialplan, eg with the provided modified "default.xml" dialplan, you can call a "skype uri" that's the word 'skype' followed by a slash and a destination: "skype/remote_skypename__OR__skypeout_phonenumber" for calling via the Skype network. Eg "skype/echo123" or "skype/+18007844444".
+
+You can use the "skype uri" of the provided dialplan also directly for a SIP softphone, eg X-Lite.
With the provided skypiax.conf.xml all incoming Skype calls will be routed to the "5000" extension, the IVR in default FreeSWITCH installation.
@@ -25,7 +27,7 @@
On a Linux machine with 3GB ram and a quad core intel6600, we got no problem with 20 concurrent calls, and plenty of room for adding more Skypiax channels (100? not tested).
-On Windows, no need to do anything special, the Skype client is lighter on CPU.
+On Windows, no need to do anything special, the Skype client is lighter on CPU.
''Skypiax is now pre-beta, but usable for testing and finding bugs :-).''
1
0
[commit] r11142 - freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax
by FreeSWITCH SVN 12 Jan '09
by FreeSWITCH SVN 12 Jan '09
12 Jan '09
Author: gmaruzz
Date: Mon Jan 12 11:50:34 2009
New Revision: 11142
Log:
skypiax: implemented anthm suggested changes, fixed switch_core_session_rwunlock(session), indented again
Modified:
freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/mod_skypiax.c
freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/skypiax_protocol.c
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 Mon Jan 12 11:50:34 2009
@@ -590,8 +590,10 @@
channel = switch_core_session_get_channel(session);
if (channel) {
switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
+ switch_core_session_rwunlock(session);
} else {
ERRORA("no channel?\n", SKYPIAX_P_LOG);
+ switch_core_session_rwunlock(session);
}
} else {
DEBUGA_SKYPE("no session\n", SKYPIAX_P_LOG);
Modified: freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/skypiax_protocol.c
==============================================================================
--- freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/skypiax_protocol.c (original)
+++ freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/skypiax_protocol.c Mon Jan 12 11:50:34 2009
@@ -1364,6 +1364,7 @@
switch_set_flag(tech_pvt, TFLAG_DTMF);
switch_mutex_unlock(tech_pvt->flag_mutex);
}
+ switch_core_session_rwunlock(session);
}
if (!strcasecmp(prop, "FAILUREREASON")) {
@@ -1634,6 +1635,7 @@
ERRORA("No channel???\n", SKYPIAX_P_LOG);
}
+ switch_core_session_rwunlock(session);
}
} else {
1
0
Author: ctrix
Date: Mon Jan 12 11:48:43 2009
New Revision: 11141
Log:
Initial empty dir for mod_airpe
Added:
freeswitch/branches/ctrix/mod_airpe/
1
0
Author: intralanman
Date: Mon Jan 12 11:41:26 2009
New Revision: 11140
Log:
Added:
freeswitch/branches/ctrix/
1
0
[commit] r11139 - freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax
by FreeSWITCH SVN 12 Jan '09
by FreeSWITCH SVN 12 Jan '09
12 Jan '09
Author: gmaruzz
Date: Mon Jan 12 11:30:42 2009
New Revision: 11139
Log:
skypiax: indent -gnu -ts4 -br -brs -cdw -lp -ce -nbfda -npcs -nprs -npsl -nbbo -saf -sai -saw -cs -bbo -nhnl -nut -sob -l90
Modified:
freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/mod_skypiax.c
freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/skypiax.h
freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/skypiax_protocol.c
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 Mon Jan 12 11:30:42 2009
@@ -59,7 +59,7 @@
static switch_status_t skypiax_codec(private_t * tech_pvt, int sample_rate, int codec_ms)
{
-switch_core_session_t *session=NULL;
+ switch_core_session_t *session = NULL;
if (switch_core_codec_init
(&tech_pvt->read_codec, "L16", NULL, sample_rate, codec_ms, 1,
@@ -103,7 +103,8 @@
switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED,
switch_core_session_get_pool(session));
switch_core_session_set_private(session, tech_pvt);
- switch_copy_string(tech_pvt->session_uuid_str, switch_core_session_get_uuid(session), sizeof(tech_pvt->session_uuid_str));
+ switch_copy_string(tech_pvt->session_uuid_str, switch_core_session_get_uuid(session),
+ sizeof(tech_pvt->session_uuid_str));
if (skypiax_codec(tech_pvt, SAMPLERATE_SKYPIAX, 20) != SWITCH_STATUS_SUCCESS) {
ERRORA("skypiax_codec FAILED\n", SKYPIAX_P_LOG);
} else {
@@ -583,7 +584,7 @@
DEBUGA_SKYPE("skype call ended\n", SKYPIAX_P_LOG);
if (tech_pvt) {
- session = switch_core_session_locate(tech_pvt->session_uuid_str);
+ session = switch_core_session_locate(tech_pvt->session_uuid_str);
if (session) {
channel = switch_core_session_get_channel(session);
@@ -814,7 +815,8 @@
skype_user);
switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].context, context);
switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].dialplan, dialplan);
- switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].destination, destination);
+ switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].destination,
+ destination);
switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].context, context);
DEBUGA_SKYPE
@@ -849,8 +851,7 @@
globals.SKYPIAX_INTERFACES[interface_id].destination);
DEBUGA_SKYPE
("interface_id=%d globals.SKYPIAX_INTERFACES[interface_id].context=%s\n",
- SKYPIAX_P_LOG, interface_id,
- globals.SKYPIAX_INTERFACES[interface_id].context);
+ SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].context);
NOTICA("STARTING interface_id=%d\n", SKYPIAX_P_LOG, interface_id);
switch_threadattr_create(&skypiax_skypeapi_thread_attr, skypiax_module_pool);
@@ -902,10 +903,10 @@
i, globals.SKYPIAX_INTERFACES[i].context);
DEBUGA_SKYPE("i=%d globals.SKYPIAX_INTERFACES[%d].dialplan=%s\n", SKYPIAX_P_LOG,
i, i, globals.SKYPIAX_INTERFACES[i].dialplan);
- DEBUGA_SKYPE("i=%d globals.SKYPIAX_INTERFACES[%d].destination=%s\n", SKYPIAX_P_LOG,
- i, i, globals.SKYPIAX_INTERFACES[i].destination);
- DEBUGA_SKYPE("i=%d globals.SKYPIAX_INTERFACES[%d].context=%s\n", SKYPIAX_P_LOG,
- i, i, globals.SKYPIAX_INTERFACES[i].context);
+ DEBUGA_SKYPE("i=%d globals.SKYPIAX_INTERFACES[%d].destination=%s\n",
+ SKYPIAX_P_LOG, i, i, globals.SKYPIAX_INTERFACES[i].destination);
+ DEBUGA_SKYPE("i=%d globals.SKYPIAX_INTERFACES[%d].context=%s\n", SKYPIAX_P_LOG, i,
+ i, globals.SKYPIAX_INTERFACES[i].context);
}
}
}
Modified: freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/skypiax.h
==============================================================================
--- freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/skypiax.h (original)
+++ freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/skypiax.h Mon Jan 12 11:30:42 2009
@@ -157,7 +157,7 @@
switch_codec_t write_codec;
switch_frame_t read_frame;
unsigned char databuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
- char session_uuid_str[SWITCH_UUID_FORMATTED_LENGTH+1];
+ char session_uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
switch_caller_profile_t *caller_profile;
switch_mutex_t *mutex;
switch_mutex_t *flag_mutex;
Modified: freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/skypiax_protocol.c
==============================================================================
--- freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/skypiax_protocol.c (original)
+++ freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/skypiax_protocol.c Mon Jan 12 11:30:42 2009
@@ -506,7 +506,7 @@
//ERRORA("tech_pvt->audiopipe[1] = %d\n", SKYPIAX_P_LOG, tech_pvt->audiopipe[1]);
if (samples != SAMPLES_PER_FRAME * sizeof(short)) {
//if (samples)
- //ERRORA("SRV PIPE READ=====> NOT GOOD samples=%u expected=%lu\n", SKYPIAX_P_LOG, samples, SAMPLES_PER_FRAME * sizeof(short));
+ //ERRORA("SRV PIPE READ=====> NOT GOOD samples=%u expected=%lu\n", SKYPIAX_P_LOG, samples, SAMPLES_PER_FRAME * sizeof(short));
assert(samples == SAMPLES_PER_FRAME * sizeof(short)); //do a crash, please
//do nothing
} else {
@@ -808,8 +808,6 @@
return (xerror != BadValue) && (xerror != BadWindow);
}
-
-
int skypiax_skype_send_message(struct SkypiaxHandles *SkypiaxHandles,
const char *message_P)
{
@@ -1353,7 +1351,7 @@
DEBUGA_SKYPE("Call %s received a DTMF: %s\n", SKYPIAX_P_LOG, id, value);
- session = switch_core_session_locate(tech_pvt->session_uuid_str);
+ session = switch_core_session_locate(tech_pvt->session_uuid_str);
channel = switch_core_session_get_channel(session);
if (channel) {
@@ -1565,7 +1563,7 @@
//FIXME *new_session=switch_loadable_module_create_interface(skypiax_endpoint_interface, pool);
- if (!strlen(tech_pvt->session_uuid_str)) {
+ if (!strlen(tech_pvt->session_uuid_str)) {
switch_core_session_t *session = NULL;
//private_t *tech_pvt = NULL;
switch_channel_t *channel = NULL;
@@ -1596,9 +1594,9 @@
switch_caller_profile_new(switch_core_session_get_pool(session),
"skypiax", tech_pvt->dialplan,
tech_pvt->callid_name,
- tech_pvt->callid_number, NULL,
- NULL, NULL, NULL,
- "mod_skypiax", tech_pvt->context,
+ tech_pvt->callid_number, NULL, NULL,
+ NULL, NULL, "mod_skypiax",
+ tech_pvt->context,
tech_pvt->destination)) != 0) {
char name[128];
//switch_snprintf(name, sizeof(name), "skypiax/%s/%s", tech_pvt->name, tech_pvt->caller_profile->destination_number);
@@ -1620,7 +1618,7 @@
switch_channel_t *channel = NULL;
if (strlen(tech_pvt->session_uuid_str)) {
- session = switch_core_session_locate(tech_pvt->session_uuid_str);
+ session = switch_core_session_locate(tech_pvt->session_uuid_str);
} else {
ERRORA("No session???\n", SKYPIAX_P_LOG);
}
@@ -1713,7 +1711,8 @@
}
return -1;
}
- switch_copy_string(tech_pvt->session_uuid_str, switch_core_session_get_uuid(session), sizeof(tech_pvt->session_uuid_str));
+ switch_copy_string(tech_pvt->session_uuid_str, switch_core_session_get_uuid(session),
+ sizeof(tech_pvt->session_uuid_str));
caller_profile = tech_pvt->caller_profile;
caller_profile->destination_number = rdest;
1
0
[commit] r11138 - freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax
by FreeSWITCH SVN 12 Jan '09
by FreeSWITCH SVN 12 Jan '09
12 Jan '09
Author: gmaruzz
Date: Mon Jan 12 11:29:26 2009
New Revision: 11138
Log:
skypiax: implemented anthm suggested changes, no more pointer to session in pvt, use uuid instead
Modified:
freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/mod_skypiax.c
freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/skypiax.h
freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/skypiax_protocol.c
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 Mon Jan 12 11:29:26 2009
@@ -59,6 +59,8 @@
static switch_status_t skypiax_codec(private_t * tech_pvt, int sample_rate, int codec_ms)
{
+switch_core_session_t *session=NULL;
+
if (switch_core_codec_init
(&tech_pvt->read_codec, "L16", NULL, sample_rate, codec_ms, 1,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL,
@@ -79,8 +81,12 @@
tech_pvt->read_frame.rate = sample_rate;
tech_pvt->read_frame.codec = &tech_pvt->read_codec;
- switch_core_session_set_read_codec(tech_pvt->session, &tech_pvt->read_codec);
- switch_core_session_set_write_codec(tech_pvt->session, &tech_pvt->write_codec);
+ session = switch_core_session_locate(tech_pvt->session_uuid_str);
+
+ switch_core_session_set_read_codec(session, &tech_pvt->read_codec);
+ switch_core_session_set_write_codec(session, &tech_pvt->write_codec);
+
+ switch_core_session_rwunlock(session);
return SWITCH_STATUS_SUCCESS;
@@ -97,7 +103,7 @@
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;
+ switch_copy_string(tech_pvt->session_uuid_str, switch_core_session_get_uuid(session), sizeof(tech_pvt->session_uuid_str));
if (skypiax_codec(tech_pvt, SAMPLERATE_SKYPIAX, 20) != SWITCH_STATUS_SUCCESS) {
ERRORA("skypiax_codec FAILED\n", SKYPIAX_P_LOG);
} else {
@@ -577,7 +583,7 @@
DEBUGA_SKYPE("skype call ended\n", SKYPIAX_P_LOG);
if (tech_pvt) {
- session = tech_pvt->session;
+ session = switch_core_session_locate(tech_pvt->session_uuid_str);
if (session) {
channel = switch_core_session_get_channel(session);
@@ -587,13 +593,13 @@
ERRORA("no channel?\n", SKYPIAX_P_LOG);
}
} else {
- ERRORA("no session?\n", SKYPIAX_P_LOG);
+ DEBUGA_SKYPE("no session\n", SKYPIAX_P_LOG);
}
} else {
ERRORA("no tech_pvt?\n", SKYPIAX_P_LOG);
}
tech_pvt->interface_state = SKYPIAX_STATE_DOWN;
- tech_pvt->session = NULL; //FIXME
+ memset(tech_pvt->session_uuid_str, '\0', sizeof(tech_pvt->session_uuid_str));
}
}
DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
Modified: freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/skypiax.h
==============================================================================
--- freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/skypiax.h (original)
+++ freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/skypiax.h Mon Jan 12 11:29:26 2009
@@ -157,7 +157,7 @@
switch_codec_t write_codec;
switch_frame_t read_frame;
unsigned char databuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
- switch_core_session_t *session;
+ char session_uuid_str[SWITCH_UUID_FORMATTED_LENGTH+1];
switch_caller_profile_t *caller_profile;
switch_mutex_t *mutex;
switch_mutex_t *flag_mutex;
Modified: freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/skypiax_protocol.c
==============================================================================
--- freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/skypiax_protocol.c (original)
+++ freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/skypiax_protocol.c Mon Jan 12 11:29:26 2009
@@ -1353,8 +1353,7 @@
DEBUGA_SKYPE("Call %s received a DTMF: %s\n", SKYPIAX_P_LOG, id, value);
- //tech_pvt = p;
- session = tech_pvt->session;
+ session = switch_core_session_locate(tech_pvt->session_uuid_str);
channel = switch_core_session_get_channel(session);
if (channel) {
@@ -1566,7 +1565,7 @@
//FIXME *new_session=switch_loadable_module_create_interface(skypiax_endpoint_interface, pool);
- if (!tech_pvt->session) { //FIXME FIXME FIXME
+ if (!strlen(tech_pvt->session_uuid_str)) {
switch_core_session_t *session = NULL;
//private_t *tech_pvt = NULL;
switch_channel_t *channel = NULL;
@@ -1620,10 +1619,10 @@
switch_core_session_t *session = NULL;
switch_channel_t *channel = NULL;
- if (tech_pvt->session) {
- session = tech_pvt->session;
+ if (strlen(tech_pvt->session_uuid_str)) {
+ session = switch_core_session_locate(tech_pvt->session_uuid_str);
} else {
- ERRORA("No tech_pvt->session???\n", SKYPIAX_P_LOG);
+ ERRORA("No session???\n", SKYPIAX_P_LOG);
}
if (session) {
channel = switch_core_session_get_channel(session);
@@ -1714,7 +1713,7 @@
}
return -1;
}
- tech_pvt->session = session;
+ switch_copy_string(tech_pvt->session_uuid_str, switch_core_session_get_uuid(session), sizeof(tech_pvt->session_uuid_str));
caller_profile = tech_pvt->caller_profile;
caller_profile->destination_number = rdest;
1
0
[commit] r11136 - freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax
by FreeSWITCH SVN 12 Jan '09
by FreeSWITCH SVN 12 Jan '09
12 Jan '09
Author: gmaruzz
Date: Mon Jan 12 06:12:05 2009
New Revision: 11136
Log:
docs
Modified:
freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/README
Modified: freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/README
==============================================================================
--- freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/README (original)
+++ freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/README Mon Jan 12 06:12:05 2009
@@ -11,22 +11,38 @@
#########################################################
#########################################################
-Skypiax is an endpoint (channel driver) that use the Skype client as an interface to the Skype network, and allows incoming and outgoing Skype calls from/to FreeSWITCH.
+Skypiax is an endpoint (channel driver) that use the Skype client as an interface to the Skype network, and allows incoming and outgoing Skype calls from/to FreeSWITCH (that can be bridged, originated, answered, etc. as in all other endpoints, eg sofia/SIP).
-Think at Skypiax as similar to OpenZAP for analog lines: for each channel you need an interface (a Skype client). So, for eg, for two concurrent calls, you will need two channels, and two Skype clients running on your machine.
+Think at Skypiax as similar to OpenZAP for analog lines: for each channel you need an interface (a Skype client). So, for eg, for two concurrent calls, you will need two channels, two Skype clients running on server.
-On Linux the Skype client uses a lot of CPU. To lower its CPU consumption, you can use the Xvfb "fake" X server and (more important) the snd-dummy ALSA "fake" sound driver.
+If your server's Skype client(s) has got the Skype credits, Skypiax works for SkypeOut calls too.
-On a Linux machine with 3GB ram and a quad core intel6600, we got no problem with 20 concurrent calls, and plenty of room for adding more Skypiax channels.
+You can use it from the dialplan, eg with the provided modified "default.xml" dialplan, you can call "sip:skype/remote_skypename__OR__skypeout_phonenumber" for calling via the Skype network from a SIP softphone to remote_skypename or to a phone number via SkypeOut, or you can call the "2908" extension from any phone to be bridged to the Skype Test Call).
+
+With the provided skypiax.conf.xml all incoming Skype calls will be routed to the "5000" extension, the IVR in default FreeSWITCH installation.
+
+On Linux the Skype client uses a lot of CPU. To lower its CPU consumption, you can use the Xvfb "fake" X server and (more important) the snd-dummy ALSA "fake" sound driver. Scripts are provided for this. But for a low number of channels it would works with regular X servers and ALSA drivers.
+
+On a Linux machine with 3GB ram and a quad core intel6600, we got no problem with 20 concurrent calls, and plenty of room for adding more Skypiax channels (100? not tested).
On Windows, no need to do anything special, the Skype client is lighter on CPU.
-More info on skypiax: http://wiki.freeswitch.org/wiki/Skypiax
- http://www.celliax.org
+
+''Skypiax is now pre-beta, but usable for testing and finding bugs :-).''
+
+
+'''You can download Skypiax source code with subversion with the command:'''
+
+svn co http://svn.freeswitch.org/svn/freeswitch/branches/gmaruzz/src/mod/endpoints… mod_skypiax
+then, follow the README file in the mod_skypiax directory.
+
+More info on skypiax:
+http://wiki.freeswitch.org/wiki/Skypiax
+http://www.celliax.org
Skypiax has been contributed to the community by:
- Giovanni Maruzzelli
- (gmaruzz at gmail dot com)
+Giovanni Maruzzelli (gmaruzz at gmail dot com)
+
#########################################################
#########################################################
#########################################################
1
0
[commit] r11135 - freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax
by FreeSWITCH SVN 12 Jan '09
by FreeSWITCH SVN 12 Jan '09
12 Jan '09
Author: gmaruzz
Date: Mon Jan 12 05:50:49 2009
New Revision: 11135
Log:
removed mod_skypiax_stuff.c
Removed:
freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/mod_skypiax_stuff.c
1
0
[commit] r11134 - in freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax: . configs
by FreeSWITCH SVN 12 Jan '09
by FreeSWITCH SVN 12 Jan '09
12 Jan '09
Author: gmaruzz
Date: Mon Jan 12 05:07:47 2009
New Revision: 11134
Log:
docs
Modified:
freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/README
freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/configs/README.skypiax_auth
freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/configs/skypiax.conf.xml
freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/configs/startskype.bat
freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/configs/startskype.sh
Modified: freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/README
==============================================================================
--- freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/README (original)
+++ freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/README Mon Jan 12 05:07:47 2009
@@ -2,7 +2,36 @@
#########################################################
#########################################################
- An example of installation
+WHAT IS SKYPIAX
+
+This software (Skypiax) uses the Skype API but is not endorsed,
+ certified or otherwise approved in any way by Skype.
+
+#########################################################
+#########################################################
+#########################################################
+
+Skypiax is an endpoint (channel driver) that use the Skype client as an interface to the Skype network, and allows incoming and outgoing Skype calls from/to FreeSWITCH.
+
+Think at Skypiax as similar to OpenZAP for analog lines: for each channel you need an interface (a Skype client). So, for eg, for two concurrent calls, you will need two channels, and two Skype clients running on your machine.
+
+On Linux the Skype client uses a lot of CPU. To lower its CPU consumption, you can use the Xvfb "fake" X server and (more important) the snd-dummy ALSA "fake" sound driver.
+
+On a Linux machine with 3GB ram and a quad core intel6600, we got no problem with 20 concurrent calls, and plenty of room for adding more Skypiax channels.
+
+On Windows, no need to do anything special, the Skype client is lighter on CPU.
+
+More info on skypiax: http://wiki.freeswitch.org/wiki/Skypiax
+ http://www.celliax.org
+
+Skypiax has been contributed to the community by:
+ Giovanni Maruzzelli
+ (gmaruzz at gmail dot com)
+#########################################################
+#########################################################
+#########################################################
+
+ An example of Skypiax installation on FreeSWITCH Linux
#########################################################
#########################################################
@@ -57,6 +86,9 @@
*** copy the skypiax configuration file
root@8-04-srv:~/freeswitch_gmaruzz# cp src/mod/endpoints/mod_skypiax/configs/skypiax.conf.xml /usr/local/freeswitch/conf/autoload_configs/
+*** optionally, copy the dialplan configuration file that contains the "skypiax" modifications (eg: you can call "sip:skype/remote_skypename__OR__skypeout_phonenumber" for calling via the Skype network from a SIP softphone to remote_skypename or to a phone number via SkypeOut, or you can call the "2908" extension from any phone to be bridged to the Skype Test Call)
+root@8-04-srv:~/freeswitch_gmaruzz# cp src/mod/endpoints/mod_skypiax/configs/default.xml /usr/local/freeswitch/conf/dialplan/
+
*** now, let's get and install the Skype client
root@8-04-srv:~/freeswitch_gmaruzz# cd ..
root@8-04-srv:~#
@@ -65,7 +97,7 @@
root@8-04-srv:~# dpkg -i skype_ubuntu-2.0.0.72-1_amd64.deb
*** now, let's get the skype configuration directory we prepared on another (desktop) machine
-*** on "How to prepare the configuration directory of Skype clients", see configs/README.skypiax_auth
+*** on "How to prepare the configuration directory of Skype clients on Linux", see configs/README.skypiax_auth
root@8-04-srv:~# cp /mnt/root/configskypenew.tgz ./
root@8-04-srv:~# tar xzf configskypenew.tgz
root@8-04-srv:~# chown root.root .Skype
@@ -102,6 +134,7 @@
=============================================
+20 idle skypiax channels:
top - 18:14:26 up 2:02, 2 users, load average: 0.03, 0.08, 0.04
Tasks: 111 total, 1 running, 110 sleeping, 0 stopped, 0 zombie
Modified: freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/configs/README.skypiax_auth
==============================================================================
--- freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/configs/README.skypiax_auth (original)
+++ freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/configs/README.skypiax_auth Mon Jan 12 05:07:47 2009
@@ -1,18 +1,34 @@
-How to use skypiax_auth
+#######################################
+HOW TO USE SKYPIAX_AUTH
+#######################################
-You will use skypiax_auth only at the setup moment, to make the Skype client asking you to authorize "skypiax" to connect to the same Skype client.
+You will use skypiax_auth only at the setup moment, to force the Skype client to ask you to authorize "skypiax" to connect to it.
Then you copy the .Skype configuration directory of the user that has launched Skype (eg: /home/maruzz/.Skype if you are maruzz) on the home directory of the user that will start Skype on the server (eg: root).
Compile skypiax_auth:
$ gcc -Wall -ggdb skypiax_auth.c -o skypiax_auth -lX11
-Start the Skype client on a desktop linux machine, logout from your autologin username if any, and login with the username and password you want to use for skypiax
+Then:
-Configure the Skype client to use the right audio devices, to not update, to not make "events", etc etc...
+1) Start the Skype client on a desktop linux machine, logout from your autologin username if any, and login with the username and password you want to use for skypiax
-Then, when satisfied, use skypiax_auth (that simulates FS-skypiax connecting to the Skype client). The Skype client will ask you to be authorized to let "skypiax" connect.
+2) Configure the Skype client to use the right audio devices, to not update, to not make "events", etc etc...
+3) Then, when satisfied, use skypiax_auth (that simulates FS-skypiax connecting to the Skype client). The Skype client will ask you to be authorized to let "skypiax" connect.
+
+4) Give the authorization and check the "not ask me again" option.
+
+5) Close (Quit) the Skype client from the tray icon, so it saves its config.
+
+6) Then, relaunch the Skype client and use skypiax_auth again, just to be sure it now succeed.
+
+7) Close (Quit) the Skype client from the tray icon, so it saves its config.
+
+*** Do the steps 1-7 for all Skype usernames you will want to use on the server (eg: one Skype username per channel)
+
+When finished wityh all the Skype usernames:
+Copy or targzip the .Skype directory and all its content on the home directory of the server user that will launch the Skype client(s).
############################
first time you use skypiax_auth
Modified: freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/configs/skypiax.conf.xml
==============================================================================
--- freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/configs/skypiax.conf.xml (original)
+++ freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/configs/skypiax.conf.xml Mon Jan 12 05:07:47 2009
@@ -29,6 +29,7 @@
<param name="tcp_srv_port" value="15559"/>
<param name="skype_user" value="skypiax2"/>
</interface>
+ <!-- following interfaces are commented out!
<interface id="3" name="skypiax3">
<param name="hold-music" value="$${moh_uri}"/>
<param name="dialplan" value="XML"/>
@@ -206,5 +207,6 @@
<param name="tcp_srv_port" value="15595"/>
<param name="skype_user" value="skypiax20"/>
</interface>
+ -->
</per_interface_settings>
</configuration>
Modified: freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/configs/startskype.bat
==============================================================================
--- freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/configs/startskype.bat (original)
+++ freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/configs/startskype.bat Mon Jan 12 05:07:47 2009
@@ -12,38 +12,41 @@
call wait 7
start Skype.exe /secondary /username:skypiax2 /password:xxx
call wait 7
-start Skype.exe /secondary /username:skypiax3 /password:xxx
-call wait 7
-start Skype.exe /secondary /username:skypiax4 /password:xxx
-call wait 7
-start Skype.exe /secondary /username:skypiax5 /password:xxx
-call wait 7
-start Skype.exe /secondary /username:skypiax6 /password:xxx
-call wait 7
-start Skype.exe /secondary /username:skypiax7 /password:xxx
-call wait 7
-start Skype.exe /secondary /username:skypiax8 /password:xxx
-call wait 7
-start Skype.exe /secondary /username:skypiax9 /password:xxx
-call wait 7
-start Skype.exe /secondary /username:skypiax10 /password:xxx
-call wait 7
-start Skype.exe /secondary /username:skypiax11 /password:xxx
-call wait 7
-start Skype.exe /secondary /username:skypiax12 /password:xxx
-call wait 7
-start Skype.exe /secondary /username:skypiax13 /password:xxx
-call wait 7
-start Skype.exe /secondary /username:skypiax14 /password:xxx
-call wait 7
-start Skype.exe /secondary /username:skypiax15 /password:xxx
-call wait 7
-start Skype.exe /secondary /username:skypiax16 /password:xxx
-call wait 7
-start Skype.exe /secondary /username:skypiax17 /password:xxx
-call wait 7
-start Skype.exe /secondary /username:skypiax18 /password:xxx
-call wait 7
-start Skype.exe /secondary /username:skypiax19 /password:xxx
-call wait 7
-start Skype.exe /secondary /username:skypiax20 /password:xxx
+REM
+REM Following Skype client instances are commented out
+REM
+REM start Skype.exe /secondary /username:skypiax3 /password:xxx
+REM call wait 7
+REM start Skype.exe /secondary /username:skypiax4 /password:xxx
+REM call wait 7
+REM start Skype.exe /secondary /username:skypiax5 /password:xxx
+REM call wait 7
+REM start Skype.exe /secondary /username:skypiax6 /password:xxx
+REM call wait 7
+REM start Skype.exe /secondary /username:skypiax7 /password:xxx
+REM call wait 7
+REM start Skype.exe /secondary /username:skypiax8 /password:xxx
+REM call wait 7
+REM start Skype.exe /secondary /username:skypiax9 /password:xxx
+REM call wait 7
+REM start Skype.exe /secondary /username:skypiax10 /password:xxx
+REM call wait 7
+REM start Skype.exe /secondary /username:skypiax11 /password:xxx
+REM call wait 7
+REM start Skype.exe /secondary /username:skypiax12 /password:xxx
+REM call wait 7
+REM start Skype.exe /secondary /username:skypiax13 /password:xxx
+REM call wait 7
+REM start Skype.exe /secondary /username:skypiax14 /password:xxx
+REM call wait 7
+REM start Skype.exe /secondary /username:skypiax15 /password:xxx
+REM call wait 7
+REM start Skype.exe /secondary /username:skypiax16 /password:xxx
+REM call wait 7
+REM start Skype.exe /secondary /username:skypiax17 /password:xxx
+REM call wait 7
+REM start Skype.exe /secondary /username:skypiax18 /password:xxx
+REM call wait 7
+REM start Skype.exe /secondary /username:skypiax19 /password:xxx
+REM call wait 7
+REM start Skype.exe /secondary /username:skypiax20 /password:xxx
Modified: freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/configs/startskype.sh
==============================================================================
--- freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/configs/startskype.sh (original)
+++ freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/configs/startskype.sh Mon Jan 12 05:07:47 2009
@@ -21,112 +21,116 @@
echo "skypiax2 xxx"| DISPLAY=:102 /usr/bin/skype --pipelogin &
sleep 7
-/usr/bin/Xvfb :103 &
-sleep 3
-
-echo "skypiax3 xxx"| DISPLAY=:103 /usr/bin/skype --pipelogin &
-
-sleep 7
-/usr/bin/Xvfb :104 &
-sleep 3
-
-echo "skypiax4 xxx"| DISPLAY=:104 /usr/bin/skype --pipelogin &
-
-sleep 7
-/usr/bin/Xvfb :105 &
-sleep 3
-
-echo "skypiax5 xxx"| DISPLAY=:105 /usr/bin/skype --pipelogin &
-
-sleep 7
-/usr/bin/Xvfb :106 &
-sleep 3
-
-echo "skypiax6 xxx"| DISPLAY=:106 /usr/bin/skype --pipelogin &
-
-sleep 7
-/usr/bin/Xvfb :107 &
-sleep 3
-
-echo "skypiax7 xxx"| DISPLAY=:107 /usr/bin/skype --pipelogin &
-
-sleep 7
-/usr/bin/Xvfb :108 &
-sleep 3
-
-echo "skypiax8 xxx"| DISPLAY=:108 /usr/bin/skype --pipelogin &
-
-sleep 7
-/usr/bin/Xvfb :109 &
-sleep 3
-
-echo "skypiax9 xxx"| DISPLAY=:109 /usr/bin/skype --pipelogin &
-
-sleep 7
-/usr/bin/Xvfb :110 &
-sleep 3
-
-echo "skypiax10 xxx"| DISPLAY=:110 /usr/bin/skype --pipelogin &
-
-sleep 7
-/usr/bin/Xvfb :111 &
-sleep 3
-
-echo "skypiax11 xxx"| DISPLAY=:111 /usr/bin/skype --pipelogin &
-
-sleep 7
-/usr/bin/Xvfb :112 &
-sleep 3
-
-echo "skypiax12 xxx"| DISPLAY=:112 /usr/bin/skype --pipelogin &
-
-sleep 7
-/usr/bin/Xvfb :113 &
-sleep 3
-
-echo "skypiax13 xxx"| DISPLAY=:113 /usr/bin/skype --pipelogin &
-
-sleep 7
-/usr/bin/Xvfb :114 &
-sleep 3
-
-echo "skypiax14 xxx"| DISPLAY=:114 /usr/bin/skype --pipelogin &
-
-sleep 7
-/usr/bin/Xvfb :115 &
-sleep 3
-
-echo "skypiax15 xxx"| DISPLAY=:115 /usr/bin/skype --pipelogin &
-
-sleep 7
-/usr/bin/Xvfb :116 &
-sleep 3
-
-echo "skypiax16 xxx"| DISPLAY=:116 /usr/bin/skype --pipelogin &
-
-sleep 7
-/usr/bin/Xvfb :117 &
-sleep 3
-
-echo "skypiax17 xxx"| DISPLAY=:117 /usr/bin/skype --pipelogin &
-
-sleep 7
-/usr/bin/Xvfb :118 &
-sleep 3
-
-echo "skypiax18 xxx"| DISPLAY=:118 /usr/bin/skype --pipelogin &
-
-sleep 7
-/usr/bin/Xvfb :119 &
-sleep 3
-
-echo "skypiax19 xxx"| DISPLAY=:119 /usr/bin/skype --pipelogin &
-
-sleep 7
-/usr/bin/Xvfb :120 &
-sleep 3
-
-echo "skypiax20 xxx"| DISPLAY=:120 /usr/bin/skype --pipelogin &
-
-sleep 7
+#################################################################
+# Following X server Skype client instances are commented out
+#################################################################
+###/usr/bin/Xvfb :103 &
+###sleep 3
+###
+###echo "skypiax3 xxx"| DISPLAY=:103 /usr/bin/skype --pipelogin &
+###
+###sleep 7
+###/usr/bin/Xvfb :104 &
+###sleep 3
+###
+###echo "skypiax4 xxx"| DISPLAY=:104 /usr/bin/skype --pipelogin &
+###
+###sleep 7
+###/usr/bin/Xvfb :105 &
+###sleep 3
+###
+###echo "skypiax5 xxx"| DISPLAY=:105 /usr/bin/skype --pipelogin &
+###
+###sleep 7
+###/usr/bin/Xvfb :106 &
+###sleep 3
+###
+###echo "skypiax6 xxx"| DISPLAY=:106 /usr/bin/skype --pipelogin &
+###
+###sleep 7
+###/usr/bin/Xvfb :107 &
+###sleep 3
+###
+###echo "skypiax7 xxx"| DISPLAY=:107 /usr/bin/skype --pipelogin &
+###
+###sleep 7
+###/usr/bin/Xvfb :108 &
+###sleep 3
+###
+###echo "skypiax8 xxx"| DISPLAY=:108 /usr/bin/skype --pipelogin &
+###
+###sleep 7
+###/usr/bin/Xvfb :109 &
+###sleep 3
+###
+###echo "skypiax9 xxx"| DISPLAY=:109 /usr/bin/skype --pipelogin &
+###
+###sleep 7
+###/usr/bin/Xvfb :110 &
+###sleep 3
+###
+###echo "skypiax10 xxx"| DISPLAY=:110 /usr/bin/skype --pipelogin &
+###
+###sleep 7
+###/usr/bin/Xvfb :111 &
+###sleep 3
+###
+###echo "skypiax11 xxx"| DISPLAY=:111 /usr/bin/skype --pipelogin &
+###
+###sleep 7
+###/usr/bin/Xvfb :112 &
+###sleep 3
+###
+###echo "skypiax12 xxx"| DISPLAY=:112 /usr/bin/skype --pipelogin &
+###
+###sleep 7
+###/usr/bin/Xvfb :113 &
+###sleep 3
+###
+###echo "skypiax13 xxx"| DISPLAY=:113 /usr/bin/skype --pipelogin &
+###
+###sleep 7
+###/usr/bin/Xvfb :114 &
+###sleep 3
+###
+###echo "skypiax14 xxx"| DISPLAY=:114 /usr/bin/skype --pipelogin &
+###
+###sleep 7
+###/usr/bin/Xvfb :115 &
+###sleep 3
+###
+###echo "skypiax15 xxx"| DISPLAY=:115 /usr/bin/skype --pipelogin &
+###
+###sleep 7
+###/usr/bin/Xvfb :116 &
+###sleep 3
+###
+###echo "skypiax16 xxx"| DISPLAY=:116 /usr/bin/skype --pipelogin &
+###
+###sleep 7
+###/usr/bin/Xvfb :117 &
+###sleep 3
+###
+###echo "skypiax17 xxx"| DISPLAY=:117 /usr/bin/skype --pipelogin &
+###
+###sleep 7
+###/usr/bin/Xvfb :118 &
+###sleep 3
+###
+###echo "skypiax18 xxx"| DISPLAY=:118 /usr/bin/skype --pipelogin &
+###
+###sleep 7
+###/usr/bin/Xvfb :119 &
+###sleep 3
+###
+###echo "skypiax19 xxx"| DISPLAY=:119 /usr/bin/skype --pipelogin &
+###
+###sleep 7
+###/usr/bin/Xvfb :120 &
+###sleep 3
+###
+###echo "skypiax20 xxx"| DISPLAY=:120 /usr/bin/skype --pipelogin &
+###
+###sleep 7
+###
1
0