Let there be PHONE CALLS!
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@16142 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
074afad5b5
commit
721c391a2b
|
@ -0,0 +1,40 @@
|
||||||
|
# #####################################
|
||||||
|
# version check qt
|
||||||
|
# #####################################
|
||||||
|
contains(QT_VERSION, ^4\.[0-5]\..*) {
|
||||||
|
message("Cannot build FsGui with Qt version $$QT_VERSION.")
|
||||||
|
error("Use at least Qt 4.6.")
|
||||||
|
}
|
||||||
|
QT += xml
|
||||||
|
TARGET = fsphone
|
||||||
|
macx:TARGET = FSPhone
|
||||||
|
TEMPLATE = app
|
||||||
|
INCLUDEPATH = ../../../src/include \
|
||||||
|
../../../libs/apr/include \
|
||||||
|
../../../libs/libteletone/src
|
||||||
|
LIBS = -L../../../.libs \
|
||||||
|
-lfreeswitch \
|
||||||
|
-lm
|
||||||
|
!win32:!macx {
|
||||||
|
# This is here to comply with the default freeswitch installation
|
||||||
|
QMAKE_LFLAGS += -Wl,-rpath,/usr/local/freeswitch/lib
|
||||||
|
LIBS += -lcrypt \
|
||||||
|
-lrt
|
||||||
|
}
|
||||||
|
SOURCES += main.cpp \
|
||||||
|
mainwindow.cpp \
|
||||||
|
fshost.cpp \
|
||||||
|
call.cpp \
|
||||||
|
mod_qsettings/mod_qsettings.cpp \
|
||||||
|
prefdialog.cpp
|
||||||
|
HEADERS += mainwindow.h \
|
||||||
|
fshost.h \
|
||||||
|
call.h \
|
||||||
|
mod_qsettings/mod_qsettings.h \
|
||||||
|
prefdialog.h
|
||||||
|
FORMS += mainwindow.ui \
|
||||||
|
prefdialog.ui
|
||||||
|
RESOURCES += resources.qrc
|
||||||
|
OTHER_FILES += conf/portaudio.conf.xml \
|
||||||
|
conf/event_socket.conf.xml \
|
||||||
|
conf/freeswitch.xml
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||||
|
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
|
||||||
|
*
|
||||||
|
* Version: MPL 1.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* Anthony Minessale II <anthm@freeswitch.org>
|
||||||
|
* Portions created by the Initial Developer are Copyright (C)
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*
|
||||||
|
* Joao Mesquita <jmesquita@freeswitch.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "call.h"
|
||||||
|
|
||||||
|
Call::Call()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Call::Call(int call_id, QString cid_name, QString cid_number, fsphone_call_direction_t direction, QString uuid) :
|
||||||
|
_call_id(call_id),
|
||||||
|
_cid_name(cid_name),
|
||||||
|
_cid_number(cid_number),
|
||||||
|
_direction(direction),
|
||||||
|
_uuid (uuid)
|
||||||
|
{
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||||
|
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
|
||||||
|
*
|
||||||
|
* Version: MPL 1.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* Anthony Minessale II <anthm@freeswitch.org>
|
||||||
|
* Portions created by the Initial Developer are Copyright (C)
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*
|
||||||
|
* Joao Mesquita <jmesquita@freeswitch.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef CALL_H
|
||||||
|
#define CALL_H
|
||||||
|
|
||||||
|
#include <QtCore>
|
||||||
|
#include <QString>
|
||||||
|
#include <fshost.h>
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FSPHONE_CALL_STATE_RINGING = 0,
|
||||||
|
FSPHONE_CALL_STATE_TRYING = 1,
|
||||||
|
FSPHONE_CALL_STATE_ANSWERED = 2
|
||||||
|
} fsphone_call_state_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FSPHONE_CALL_DIRECTION_INBOUND = 0,
|
||||||
|
FSPHONE_CALL_DIRECTION_OUTBOUND = 1
|
||||||
|
} fsphone_call_direction_t;
|
||||||
|
|
||||||
|
class Call
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Call(void);
|
||||||
|
Call(int call_id, QString cid_name, QString cid_number, fsphone_call_direction_t direction, QString uuid);
|
||||||
|
QString getCidName(void) { return _cid_name; }
|
||||||
|
QString getCidNumber(void) { return _cid_number; }
|
||||||
|
int getCallID(void) { return _call_id; }
|
||||||
|
QString getUUID(void) { return _uuid; }
|
||||||
|
void setbUUID(QString uuid) { _buuid = uuid; }
|
||||||
|
fsphone_call_direction_t getDirection() { return _direction; }
|
||||||
|
fsphone_call_state_t getState() { return _state; }
|
||||||
|
void setState(fsphone_call_state_t state) { _state = state; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
int _call_id;
|
||||||
|
QString _cid_name;
|
||||||
|
QString _cid_number;
|
||||||
|
fsphone_call_direction_t _direction;
|
||||||
|
QString _uuid;
|
||||||
|
QString _buuid;
|
||||||
|
fsphone_call_state_t _state;
|
||||||
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(Call)
|
||||||
|
|
||||||
|
#endif // CALL_H
|
|
@ -0,0 +1,34 @@
|
||||||
|
<include>
|
||||||
|
<!--<gateway name="default">-->
|
||||||
|
<!--/// account username *required* ///-->
|
||||||
|
<!--<param name="username" value="cluecon"/>-->
|
||||||
|
<!--/// auth realm: *optional* same as gateway name, if blank ///-->
|
||||||
|
<!--<param name="realm" value="asterlink.com"/>-->
|
||||||
|
<!--/// username to use in from: *optional* same as username, if blank ///-->
|
||||||
|
<!--<param name="from-user" value="cluecon"/>-->
|
||||||
|
<!--/// domain to use in from: *optional* same as realm, if blank ///-->
|
||||||
|
<!--<param name="from-domain" value="asterlink.com"/>-->
|
||||||
|
<!--/// account password *required* ///-->
|
||||||
|
<!--<param name="password" value="cluecon"/>-->
|
||||||
|
<!--/// extension for inbound calls: *optional* same as username, if blank ///-->
|
||||||
|
<!--<param name="extension" value="cluecon"/>-->
|
||||||
|
<!--/// proxy host: *optional* same as realm, if blank ///-->
|
||||||
|
<!--<param name="proxy" value="asterlink.com"/>-->
|
||||||
|
<!--/// send register to this proxy: *optional* same as proxy, if blank ///-->
|
||||||
|
<!--<param name="register-proxy" value="mysbc.com"/>-->
|
||||||
|
<!--/// expire in seconds: *optional* 3600, if blank ///-->
|
||||||
|
<!--<param name="expire-seconds" value="60"/>-->
|
||||||
|
<!--/// do not register ///-->
|
||||||
|
<!--<param name="register" value="false"/>-->
|
||||||
|
<!-- which transport to use for register -->
|
||||||
|
<!--<param name="register-transport" value="udp"/>-->
|
||||||
|
<!--How many seconds before a retry when a failure or timeout occurs -->
|
||||||
|
<!--<param name="retry-seconds" value="30"/>-->
|
||||||
|
<!--Use the callerid of an inbound call in the from field on outbound calls via this gateway -->
|
||||||
|
<!--<param name="caller-id-in-from" value="false"/>-->
|
||||||
|
<!--extra sip params to send in the contact-->
|
||||||
|
<!--<param name="contact-params" value="tport=tcp"/>-->
|
||||||
|
<!--send an options ping every x seconds, failure will unregister and/or mark it down-->
|
||||||
|
<!--<param name="ping" value="25"/>-->
|
||||||
|
<!--</gateway>-->
|
||||||
|
</include>
|
|
@ -0,0 +1,8 @@
|
||||||
|
<configuration name="event_socket.conf" description="Socket Client">
|
||||||
|
<settings>
|
||||||
|
<param name="nat-map" value="false"/>
|
||||||
|
<param name="listen-ip" value="127.0.0.1"/>
|
||||||
|
<param name="listen-port" value="8021"/>
|
||||||
|
<param name="password" value="ClueCon"/>
|
||||||
|
</settings>
|
||||||
|
</configuration>
|
Binary file not shown.
|
@ -0,0 +1,267 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<document type="freeswitch/xml">
|
||||||
|
<X-PRE-PROCESS cmd="set" data="auto_answer=false"/>
|
||||||
|
<X-PRE-PROCESS cmd="set" data="domain=$${local_ip_v4}"/>
|
||||||
|
<X-PRE-PROCESS cmd="set" data="hold_music=local_stream://moh"/>
|
||||||
|
<X-PRE-PROCESS cmd="set" data="codec_prefs=CELT@48000h,G7221@32000h,G7221@16000h,G722,PCMU,PCMA,GSM"/>
|
||||||
|
<X-PRE-PROCESS cmd="set" data="external_rtp_ip=stun:stun.freeswitch.org"/>
|
||||||
|
<X-PRE-PROCESS cmd="set" data="external_sip_ip=stun:stun.freeswitch.org"/>
|
||||||
|
<X-PRE-PROCESS cmd="set" data="outbound_caller_name=FreeSWITCH"/>
|
||||||
|
<X-PRE-PROCESS cmd="set" data="outbound_caller_id=0000000000"/>
|
||||||
|
<X-PRE-PROCESS cmd="set" data="console_loglevel=info"/>
|
||||||
|
<X-PRE-PROCESS cmd="set" data="default_gateway=default"/>
|
||||||
|
<X-PRE-PROCESS cmd="set" data="us-ring=%(2000, 4000, 440.0, 480.0)"/>
|
||||||
|
<X-PRE-PROCESS cmd="set" data="bong-ring=v=-7;%(100,0,941.0,1477.0);v=-7;>=2;+=.1;%(1400,0,350,440)"/>
|
||||||
|
<X-PRE-PROCESS cmd="set" data="sit=%(274,0,913.8);%(274,0,1370.6);%(380,0,1776.7)"/>
|
||||||
|
|
||||||
|
<section name="configuration" description="Various Configuration">
|
||||||
|
<configuration name="cdr_csv.conf" description="CDR CSV Format">
|
||||||
|
<settings>
|
||||||
|
<param name="default-template" value="example"/>
|
||||||
|
<param name="rotate-on-hup" value="true"/>
|
||||||
|
<param name="legs" value="a"/>
|
||||||
|
</settings>
|
||||||
|
<templates>
|
||||||
|
<template name="example">"${caller_id_name}","${caller_id_number}","${destination_number}","${context}","${start_stamp}","${answer_stamp}","${end_stamp}","${duration}","${billsec}","${hangup_cause}","${uuid}","${bleg_uuid}","${accountcode}","${read_codec}","${write_codec}"</template>
|
||||||
|
</templates>
|
||||||
|
</configuration>
|
||||||
|
|
||||||
|
<configuration name="console.conf" description="Console Logger">
|
||||||
|
<mappings>
|
||||||
|
<map name="all" value="console,debug,info,notice,warning,err,crit,alert"/>
|
||||||
|
</mappings>
|
||||||
|
<settings>
|
||||||
|
<param name="colorize" value="true"/>
|
||||||
|
<param name="loglevel" value="$${console_loglevel}"/>
|
||||||
|
</settings>
|
||||||
|
</configuration>
|
||||||
|
|
||||||
|
<configuration name="enum.conf" description="ENUM Module">
|
||||||
|
<settings>
|
||||||
|
<param name="default-root" value="e164.org"/>
|
||||||
|
<param name="default-isn-root" value="freenum.org"/>
|
||||||
|
<param name="query-timeout" value="10"/>
|
||||||
|
<param name="auto-reload" value="true"/>
|
||||||
|
</settings>
|
||||||
|
<routes>
|
||||||
|
<route service="E2U+SIP" regex="sip:(.*)" replace="sofia/softphone/$1"/>
|
||||||
|
</routes>
|
||||||
|
</configuration>
|
||||||
|
|
||||||
|
<configuration name="qsettings.conf" description="configures our mod_qsettings">
|
||||||
|
<bindings value="dialplan" />
|
||||||
|
</configuration>
|
||||||
|
|
||||||
|
<configuration name="local_stream.conf" description="stream files from local dir">
|
||||||
|
<directory name="moh/48000" path="$${base_dir}/sounds/music/48000">
|
||||||
|
<param name="rate" value="48000"/>
|
||||||
|
<param name="shuffle" value="true"/>
|
||||||
|
<param name="channels" value="1"/>
|
||||||
|
<param name="interval" value="10"/>
|
||||||
|
<param name="timer-name" value="soft"/>
|
||||||
|
</directory>
|
||||||
|
</configuration>
|
||||||
|
|
||||||
|
<configuration name="logfile.conf" description="File Logging">
|
||||||
|
<settings>
|
||||||
|
<param name="rotate-on-hup" value="true"/>
|
||||||
|
</settings>
|
||||||
|
<profiles>
|
||||||
|
<profile name="default">
|
||||||
|
<settings>
|
||||||
|
</settings>
|
||||||
|
<mappings>
|
||||||
|
<map name="all" value="debug,info,notice,warning,err,crit,alert"/>
|
||||||
|
</mappings>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
</configuration>
|
||||||
|
|
||||||
|
<configuration name="modules.conf" description="Modules">
|
||||||
|
<modules>
|
||||||
|
<load module="mod_console"/>
|
||||||
|
<load module="mod_logfile"/>
|
||||||
|
<load module="mod_enum"/>
|
||||||
|
<load module="mod_cdr_csv"/>
|
||||||
|
<load module="mod_portaudio"/>
|
||||||
|
<load module="mod_sofia"/>
|
||||||
|
<load module="mod_loopback"/>
|
||||||
|
<load module="mod_commands"/>
|
||||||
|
<load module="mod_dptools"/>
|
||||||
|
<load module="mod_dialplan_xml"/>
|
||||||
|
<load module="mod_voipcodecs"/>
|
||||||
|
<load module="mod_ilbc"/>
|
||||||
|
<load module="mod_speex"/>
|
||||||
|
<load module="mod_celt"/>
|
||||||
|
<load module="mod_siren"/>
|
||||||
|
<load module="mod_sndfile"/>
|
||||||
|
<load module="mod_tone_stream"/>
|
||||||
|
<load module="mod_local_stream"/>
|
||||||
|
</modules>
|
||||||
|
</configuration>
|
||||||
|
|
||||||
|
<configuration name="post_load_modules.conf" description="Modules">
|
||||||
|
<modules>
|
||||||
|
</modules>
|
||||||
|
</configuration>
|
||||||
|
|
||||||
|
<configuration name="sofia.conf" description="sofia Endpoint">
|
||||||
|
<global_settings>
|
||||||
|
<param name="log-level" value="0"/>
|
||||||
|
<param name="auto-restart" value="true"/>
|
||||||
|
<param name="debug-presence" value="0"/>
|
||||||
|
</global_settings>
|
||||||
|
<profiles>
|
||||||
|
<profile name="softphone">
|
||||||
|
<gateways>
|
||||||
|
<X-PRE-PROCESS cmd="include" data="accounts/*.xml"/>
|
||||||
|
</gateways>
|
||||||
|
<settings>
|
||||||
|
<!--<param name="media-option" value="bypass-media-after-att-xfer"/>-->
|
||||||
|
<param name="user-agent-string" value="FreeSWITCH/FSPhone"/>
|
||||||
|
<!-- <param name="user-agent-string" value="FreeSWITCH Rocks!"/> -->
|
||||||
|
<param name="debug" value="0"/>
|
||||||
|
<param name="sip-trace" value="no"/>
|
||||||
|
<param name="context" value="public"/>
|
||||||
|
<param name="rfc2833-pt" value="101"/>
|
||||||
|
<!-- port to bind to for sip traffic -->
|
||||||
|
<param name="sip-port" value="12345"/>
|
||||||
|
<param name="dialplan" value="XML"/>
|
||||||
|
<param name="dtmf-duration" value="100"/>
|
||||||
|
<param name="codec-prefs" value="$${codec_prefs}"/>
|
||||||
|
<param name="use-rtp-timer" value="true"/>
|
||||||
|
<param name="rtp-timer-name" value="soft"/>
|
||||||
|
<!-- ip address to use for rtp, DO NOT USE HOSTNAMES ONLY IP ADDRESSES -->
|
||||||
|
<param name="rtp-ip" value="$${local_ip_v4}"/>
|
||||||
|
<!-- ip address to bind to, DO NOT USE HOSTNAMES ONLY IP ADDRESSES -->
|
||||||
|
<param name="sip-ip" value="$${local_ip_v4}"/>
|
||||||
|
<param name="hold-music" value="$${hold_music}"/>
|
||||||
|
<param name="apply-nat-acl" value="rfc1918"/>
|
||||||
|
<!--<param name="enable-timer" value="false"/>-->
|
||||||
|
<!--<param name="enable-100rel" value="true"/>-->
|
||||||
|
<!--<param name="minimum-session-expires" value="120"/>-->
|
||||||
|
<!--<param name="dtmf-type" value="info"/>-->
|
||||||
|
<param name="manage-presence" value="false"/>
|
||||||
|
<!--<param name="bitpacking" value="aal2"/> -->
|
||||||
|
<param name="max-proceeding" value="3"/>
|
||||||
|
<!--<param name="session-timeout" value="120"/>-->
|
||||||
|
<!--set to 'greedy' if you want your codec list to take precedence -->
|
||||||
|
<param name="inbound-codec-negotiation" value="generous"/>
|
||||||
|
<!-- if you want to send any special bind params of your own -->
|
||||||
|
<!--<param name="bind-params" value="transport=udp"/>-->
|
||||||
|
<!--Uncomment to let calls hit the dialplan *before* you decide if the codec is ok-->
|
||||||
|
<!--<param name="inbound-late-negotiation" value="true"/>-->
|
||||||
|
<!--<param name="accept-blind-reg" value="true"/> -->
|
||||||
|
<!--<param name="accept-blind-auth" value="true"/> -->
|
||||||
|
<!--<param name="suppress-cng" value="true"/> -->
|
||||||
|
<param name="nonce-ttl" value="60"/>
|
||||||
|
<!--<param name="NDLB-broken-auth-hash" value="true"/>-->
|
||||||
|
<!--<param name="NDLB-received-in-nat-reg-contact" value="true"/>-->
|
||||||
|
<param name="auth-calls" value="false"/>
|
||||||
|
<param name="auth-all-packets" value="false"/>
|
||||||
|
<param name="ext-rtp-ip" value="$${external_rtp_ip}"/>
|
||||||
|
<param name="ext-sip-ip" value="$${external_sip_ip}"/>
|
||||||
|
<!-- rtp inactivity timeout -->
|
||||||
|
<param name="rtp-timeout-sec" value="300"/>
|
||||||
|
<param name="rtp-hold-timeout-sec" value="1800"/>
|
||||||
|
<!-- VAD choose one (out is a good choice); -->
|
||||||
|
<!-- <param name="vad" value="in"/> -->
|
||||||
|
<!-- <param name="vad" value="out"/> -->
|
||||||
|
<!-- <param name="vad" value="both"/> -->
|
||||||
|
<param name="disable-register" value="true"/>
|
||||||
|
<!--<param name="NDLB-force-rport" value="true"/>-->
|
||||||
|
<param name="challenge-realm" value="auto_from"/>
|
||||||
|
<!--<param name="disable-rtp-auto-adjust" value="true"/>-->
|
||||||
|
<!--<param name="inbound-use-callid-as-uuid" value="true"/>-->
|
||||||
|
<!--<param name="outbound-use-uuid-as-callid" value="true"/>-->
|
||||||
|
<!--<param name="auto-rtp-bugs" data="clear"/>-->
|
||||||
|
</settings>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
</configuration>
|
||||||
|
|
||||||
|
<configuration name="switch.conf" description="Core Configuration">
|
||||||
|
<cli-keybindings>
|
||||||
|
<key name="1" value="help"/>
|
||||||
|
<key name="2" value="status"/>
|
||||||
|
<key name="3" value="pa answer"/>
|
||||||
|
<key name="4" value="pa hangup"/>
|
||||||
|
<key name="5" value="sofia status"/>
|
||||||
|
<key name="6" value="reloadxml"/>
|
||||||
|
<key name="7" value="console loglevel 0"/>
|
||||||
|
<key name="8" value="console loglevel 7"/>
|
||||||
|
<key name="9" value="sofia status profile softphone"/>
|
||||||
|
<key name="10" value="fsctl pause"/>
|
||||||
|
<key name="11" value="fsctl resume"/>
|
||||||
|
<key name="12" value="version"/>
|
||||||
|
</cli-keybindings>
|
||||||
|
<settings>
|
||||||
|
<param name="colorize-console" value="true"/>
|
||||||
|
<param name="max-sessions" value="20"/>
|
||||||
|
<param name="sessions-per-second" value="5"/>
|
||||||
|
<param name="loglevel" value="debug"/>
|
||||||
|
<param name="crash-protection" value="false"/>
|
||||||
|
<param name="dump-cores" value="yes"/>
|
||||||
|
<param name="rtp-start-port" value="16384"/>
|
||||||
|
<param name="rtp-end-port" value="16484"/>
|
||||||
|
</settings>
|
||||||
|
</configuration>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section name="dialplan" description="Regex/XML Dialplan">
|
||||||
|
<context name="default">
|
||||||
|
<extension name="codec_and_sip_uri">
|
||||||
|
<condition field="destination_number" expression="^sip:(.*):(.*)$">
|
||||||
|
<action application="bridge" data="{absolute_codec_string=$1}sofia/softphone/$2"/>
|
||||||
|
</condition>
|
||||||
|
</extension>
|
||||||
|
<extension name="sip_uri">
|
||||||
|
<condition field="destination_number" expression="^sip:(.*)$">
|
||||||
|
<action application="bridge" data="sofia/softphone/$1"/>
|
||||||
|
</condition>
|
||||||
|
</extension>
|
||||||
|
<extension name="codec_and_number">
|
||||||
|
<condition field="destination_number" expression="^(.*):(.*)@(.*)$">
|
||||||
|
<action application="bridge" data="{absolute_codec_string=$1}sofia/gateway/$3/$2"/>
|
||||||
|
</condition>
|
||||||
|
</extension>
|
||||||
|
<extension name="number">
|
||||||
|
<condition field="destination_number" expression="^(.*)@(.*)$">
|
||||||
|
<action application="bridge" data="sofia/gateway/$2/$1"/>
|
||||||
|
</condition>
|
||||||
|
</extension>
|
||||||
|
<extension name="number">
|
||||||
|
<condition field="destination_number" expression="^(.*)$">
|
||||||
|
<action application="bridge" data="sofia/gateway/${default_gateway}/$1"/>
|
||||||
|
</condition>
|
||||||
|
</extension>
|
||||||
|
</context>
|
||||||
|
<context name="public">
|
||||||
|
<extension name="public_extensions">
|
||||||
|
<condition field="$${auto_answer}" expression="^true$"/>
|
||||||
|
<condition field="destination_number" expression="^(.*)$">
|
||||||
|
<action application="info"/>
|
||||||
|
<action application="bridge" data="portaudio/auto_answer"/>
|
||||||
|
</condition>
|
||||||
|
</extension>
|
||||||
|
<extension name="public_extensions">
|
||||||
|
<condition field="${sip_to_params}" expression="intercom=true"/>
|
||||||
|
<condition field="${alert_info}" expression="Ring;Answer"/>
|
||||||
|
<condition field="destination_number" expression="^(.*)$">
|
||||||
|
<action application="info"/>
|
||||||
|
<action application="bridge" data="portaudio/auto_answer"/>
|
||||||
|
</condition>
|
||||||
|
</extension>
|
||||||
|
<extension name="public_extensions">
|
||||||
|
<condition field="destination_number" expression="^(.*)$">
|
||||||
|
<action application="info"/>
|
||||||
|
<action application="set" data="ringback=${us-ring}"/>
|
||||||
|
<action application="pre_answer"/>
|
||||||
|
<action application="bridge" data="portaudio"/>
|
||||||
|
</condition>
|
||||||
|
</extension>
|
||||||
|
</context>
|
||||||
|
</section>
|
||||||
|
</document>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
<configuration name="portaudio.conf" description="Soundcard Endpoint">
|
||||||
|
<settings>
|
||||||
|
<param name="indev" value="${indev}"/>
|
||||||
|
<!-- device to use for output -->
|
||||||
|
<param name="outdev" value="${outdev}"/>
|
||||||
|
<!--<param name="ringdev" value="${ringdev}"/>-->
|
||||||
|
<param name="ring-file" value="${ring-file}"/>
|
||||||
|
<param name="ring-interval" value="${ring-interval}"/>
|
||||||
|
<param name="hold-file" value="$${hold_music}"/>
|
||||||
|
<!--<param name="timer-name" value="soft"/>-->
|
||||||
|
<param name="dialplan" value="XML"/>
|
||||||
|
<param name="cid-name" value="$${outbound_caller_name}"/>
|
||||||
|
<param name="cid-num" value="$${outbound_caller_number}"/>
|
||||||
|
<param name="sample-rate" value="48000"/>
|
||||||
|
<param name="codec-ms" value="10"/>
|
||||||
|
</settings>
|
||||||
|
</configuration>
|
|
@ -0,0 +1,352 @@
|
||||||
|
/*
|
||||||
|
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||||
|
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
|
||||||
|
*
|
||||||
|
* Version: MPL 1.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* Anthony Minessale II <anthm@freeswitch.org>
|
||||||
|
* Portions created by the Initial Developer are Copyright (C)
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*
|
||||||
|
* Joao Mesquita <jmesquita@freeswitch.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <QtGui>
|
||||||
|
#include "fshost.h"
|
||||||
|
#include "call.h"
|
||||||
|
#include "mod_qsettings/mod_qsettings.h"
|
||||||
|
|
||||||
|
/* Declare it globally */
|
||||||
|
FSHost g_FSHost;
|
||||||
|
|
||||||
|
FSHost::FSHost(QObject *parent) :
|
||||||
|
QThread(parent)
|
||||||
|
{
|
||||||
|
/* Initialize libs & globals */
|
||||||
|
printf("Initializing globals...\n");
|
||||||
|
switch_core_setrlimits();
|
||||||
|
switch_core_set_globals();
|
||||||
|
|
||||||
|
qRegisterMetaType<Call>("Call");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void FSHost::run(void)
|
||||||
|
{
|
||||||
|
switch_core_flag_t flags = SCF_USE_SQL | SCF_USE_AUTO_NAT;
|
||||||
|
const char *err = NULL;
|
||||||
|
switch_bool_t console = SWITCH_FALSE;
|
||||||
|
switch_status_t destroy_status;
|
||||||
|
|
||||||
|
/* Create directory structure for softphone with default configs */
|
||||||
|
QDir conf_dir = QDir(QDir::home());
|
||||||
|
if (!conf_dir.exists(".fsphone"))
|
||||||
|
{
|
||||||
|
conf_dir.mkpath(".fsphone/conf/accounts");
|
||||||
|
conf_dir.mkpath(".fsphone/templates");
|
||||||
|
QFile rootXML(":/confs/freeswitch.xml");
|
||||||
|
QString dest = QString("%1/.fsphone/conf/freeswitch.xml").arg(conf_dir.absolutePath());
|
||||||
|
rootXML.copy(dest);
|
||||||
|
|
||||||
|
QFile defaultAccount(":/confs/example.xml");
|
||||||
|
dest = QString("%1/.fsphone/conf/accounts/example.xml").arg(conf_dir.absolutePath());
|
||||||
|
defaultAccount.copy(dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set all directories to the home user directory */
|
||||||
|
if (conf_dir.cd(".fsphone"))
|
||||||
|
{
|
||||||
|
SWITCH_GLOBAL_dirs.conf_dir = (char *) malloc(strlen(QString("%1/conf").arg(conf_dir.absolutePath()).toAscii().constData()) + 1);
|
||||||
|
if (!SWITCH_GLOBAL_dirs.conf_dir) {
|
||||||
|
emit coreLoadingError("Cannot allocate memory for conf_dir.");
|
||||||
|
}
|
||||||
|
strcpy(SWITCH_GLOBAL_dirs.conf_dir, QString("%1/conf").arg(conf_dir.absolutePath()).toAscii().constData());
|
||||||
|
|
||||||
|
SWITCH_GLOBAL_dirs.log_dir = (char *) malloc(strlen(QString("%1/log").arg(conf_dir.absolutePath()).toAscii().constData()) + 1);
|
||||||
|
if (!SWITCH_GLOBAL_dirs.log_dir) {
|
||||||
|
emit coreLoadingError("Cannot allocate memory for log_dir.");
|
||||||
|
}
|
||||||
|
strcpy(SWITCH_GLOBAL_dirs.log_dir, QString("%1/log").arg(conf_dir.absolutePath()).toAscii().constData());
|
||||||
|
|
||||||
|
SWITCH_GLOBAL_dirs.run_dir = (char *) malloc(strlen(QString("%1/run").arg(conf_dir.absolutePath()).toAscii().constData()) + 1);
|
||||||
|
if (!SWITCH_GLOBAL_dirs.run_dir) {
|
||||||
|
emit coreLoadingError("Cannot allocate memory for run_dir.");
|
||||||
|
}
|
||||||
|
strcpy(SWITCH_GLOBAL_dirs.run_dir, QString("%1/run").arg(conf_dir.absolutePath()).toAscii().constData());
|
||||||
|
|
||||||
|
SWITCH_GLOBAL_dirs.db_dir = (char *) malloc(strlen(QString("%1/db").arg(conf_dir.absolutePath()).toAscii().constData()) + 1);
|
||||||
|
if (!SWITCH_GLOBAL_dirs.db_dir) {
|
||||||
|
emit coreLoadingError("Cannot allocate memory for db_dir.");
|
||||||
|
}
|
||||||
|
strcpy(SWITCH_GLOBAL_dirs.db_dir, QString("%1/db").arg(conf_dir.absolutePath()).toAscii().constData());
|
||||||
|
|
||||||
|
SWITCH_GLOBAL_dirs.script_dir = (char *) malloc(strlen(QString("%1/script").arg(conf_dir.absolutePath()).toAscii().constData()) + 1);
|
||||||
|
if (!SWITCH_GLOBAL_dirs.script_dir) {
|
||||||
|
emit coreLoadingError("Cannot allocate memory for script_dir.");
|
||||||
|
}
|
||||||
|
strcpy(SWITCH_GLOBAL_dirs.script_dir, QString("%1/script").arg(conf_dir.absolutePath()).toAscii().constData());
|
||||||
|
|
||||||
|
SWITCH_GLOBAL_dirs.htdocs_dir = (char *) malloc(strlen(QString("%1/htdocs").arg(conf_dir.absolutePath()).toAscii().constData()) + 1);
|
||||||
|
if (!SWITCH_GLOBAL_dirs.htdocs_dir) {
|
||||||
|
emit coreLoadingError("Cannot allocate memory for htdocs_dir.");
|
||||||
|
}
|
||||||
|
strcpy(SWITCH_GLOBAL_dirs.htdocs_dir, QString("%1/htdocs").arg(conf_dir.absolutePath()).toAscii().constData());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If you need to override configuration directories, you need to change them in the SWITCH_GLOBAL_dirs global structure */
|
||||||
|
printf("Initializing core...\n");
|
||||||
|
/* Initialize the core and load modules, that will startup FS completely */
|
||||||
|
if (switch_core_init_and_modload(flags, console, &err) != SWITCH_STATUS_SUCCESS) {
|
||||||
|
fprintf(stderr, "Failed to initialize FreeSWITCH's core: %s\n", err);
|
||||||
|
emit coreLoadingError(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Everything OK, Entering runtime loop.\n");
|
||||||
|
|
||||||
|
if (switch_event_bind("FSHost", SWITCH_EVENT_ALL, SWITCH_EVENT_SUBCLASS_ANY, eventHandlerCallback, NULL) != SWITCH_STATUS_SUCCESS) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load our QSettings module */
|
||||||
|
if (switch_loadable_module_build_dynamic("mod_qsettings",mod_qsettings_load,NULL,mod_qsettings_shutdown,SWITCH_FALSE) != SWITCH_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't load mod_qsettings\n");
|
||||||
|
}
|
||||||
|
QString res;
|
||||||
|
sendCmd("load", "mod_event_socket", &res);
|
||||||
|
emit ready();
|
||||||
|
/* Go into the runtime loop. If the argument is true, this basically sets runtime.running = 1 and loops while that is set
|
||||||
|
* If its false, it initializes the libedit for the console, then does the same thing
|
||||||
|
*/
|
||||||
|
switch_core_runtime_loop(!console);
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
|
||||||
|
switch_event_unbind_callback(eventHandlerCallback);
|
||||||
|
/* When the runtime loop exits, its time to shutdown */
|
||||||
|
destroy_status = switch_core_destroy();
|
||||||
|
if (destroy_status == SWITCH_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("We have properly shutdown the core.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch_status_t FSHost::processAlegEvent(switch_event_t * event, QString uuid)
|
||||||
|
{
|
||||||
|
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||||
|
Call * call = _active_calls.value(uuid);
|
||||||
|
/* Inbound call */
|
||||||
|
if (call->getDirection() == FSPHONE_CALL_DIRECTION_INBOUND)
|
||||||
|
{
|
||||||
|
switch(event->event_id) {
|
||||||
|
case SWITCH_EVENT_CHANNEL_ANSWER:
|
||||||
|
{
|
||||||
|
call->setbUUID(switch_event_get_header_nil(event, "Other-Leg-Unique-ID"));
|
||||||
|
_bleg_uuids.insert(switch_event_get_header_nil(event, "Other-Leg-Unique-ID"), uuid);
|
||||||
|
call->setState(FSPHONE_CALL_STATE_ANSWERED);
|
||||||
|
emit answered(uuid);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SWITCH_EVENT_CHANNEL_HANGUP_COMPLETE:
|
||||||
|
{
|
||||||
|
emit hungup(_active_calls.take(uuid));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SWITCH_EVENT_CHANNEL_STATE:
|
||||||
|
{
|
||||||
|
printf("CHANNEL_STATE Answer-State: %s | Channel-State: %s | %s | %s\n", switch_event_get_header_nil(event, "Answer-State"),switch_event_get_header_nil(event, "Channel-State"), uuid.toAscii().constData(), switch_event_get_header_nil(event, "Other-Leg-Unique-ID"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Outbound call */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch(event->event_id)
|
||||||
|
{
|
||||||
|
case SWITCH_EVENT_CHANNEL_BRIDGE:
|
||||||
|
{
|
||||||
|
_active_calls.value(uuid)->setbUUID(switch_event_get_header_nil(event, "Other-Leg-Unique-ID"));
|
||||||
|
_bleg_uuids.insert(switch_event_get_header_nil(event, "Other-Leg-Unique-ID"), uuid);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SWITCH_EVENT_CHANNEL_HANGUP_COMPLETE:
|
||||||
|
{
|
||||||
|
if (call->getState() == FSPHONE_CALL_STATE_TRYING)
|
||||||
|
{
|
||||||
|
emit callFailed(uuid);
|
||||||
|
_active_calls.take(uuid);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
printf("A leg: %s(%s)\n",switch_event_name(event->event_id), switch_event_get_header_nil(event, "Event-Subclass"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch_status_t FSHost::processBlegEvent(switch_event_t * event, QString buuid)
|
||||||
|
{
|
||||||
|
QString uuid = _bleg_uuids.value(buuid);
|
||||||
|
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||||
|
Call * call = _active_calls.value(uuid);
|
||||||
|
/* Inbound call */
|
||||||
|
if (call->getDirection() == FSPHONE_CALL_DIRECTION_INBOUND)
|
||||||
|
{
|
||||||
|
qDebug() << " Inbound call";
|
||||||
|
}
|
||||||
|
/* Outbound call */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch(event->event_id)
|
||||||
|
{
|
||||||
|
case SWITCH_EVENT_CHANNEL_ANSWER:
|
||||||
|
{
|
||||||
|
emit answered(uuid);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SWITCH_EVENT_CHANNEL_HANGUP_COMPLETE:
|
||||||
|
{
|
||||||
|
emit hungup(_active_calls.take(uuid));
|
||||||
|
_bleg_uuids.take(buuid);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SWITCH_EVENT_CHANNEL_STATE:
|
||||||
|
{
|
||||||
|
if (QString(switch_event_get_header_nil(event, "Answer-State")) == "early")
|
||||||
|
{
|
||||||
|
call->setState(FSPHONE_CALL_STATE_RINGING);
|
||||||
|
emit ringing(uuid);
|
||||||
|
}
|
||||||
|
//printEventHeaders(event);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
printf("B leg: %s(%s)\n",switch_event_name(event->event_id), switch_event_get_header_nil(event, "Event-Subclass"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FSHost::generalEventHandler(switch_event_t *event)
|
||||||
|
{
|
||||||
|
QString uuid = switch_event_get_header_nil(event, "Unique-ID");
|
||||||
|
|
||||||
|
if (_bleg_uuids.contains(uuid))
|
||||||
|
{
|
||||||
|
if (processBlegEvent(event, uuid) == SWITCH_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_active_calls.contains(uuid))
|
||||||
|
{
|
||||||
|
if (processAlegEvent(event, uuid) == SWITCH_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is how we identify new calls, inbound and outbound */
|
||||||
|
switch(event->event_id) {
|
||||||
|
case SWITCH_EVENT_CUSTOM:
|
||||||
|
{
|
||||||
|
if (strcmp(event->subclass_name, "portaudio::ringing") == 0 && !_active_calls.contains(uuid))
|
||||||
|
{
|
||||||
|
Call *call = new Call(atoi(switch_event_get_header_nil(event, "call_id")),
|
||||||
|
switch_event_get_header_nil(event, "Caller-Caller-ID-Name"),
|
||||||
|
switch_event_get_header_nil(event, "Caller-Caller-ID-Number"),
|
||||||
|
FSPHONE_CALL_DIRECTION_INBOUND,
|
||||||
|
uuid);
|
||||||
|
_active_calls.insert(uuid, call);
|
||||||
|
call->setState(FSPHONE_CALL_STATE_RINGING);
|
||||||
|
emit ringing(uuid);
|
||||||
|
}
|
||||||
|
else if (strcmp(event->subclass_name, "portaudio::makecall") == 0)
|
||||||
|
{
|
||||||
|
Call *call = new Call(atoi(switch_event_get_header_nil(event, "call_id")),NULL,
|
||||||
|
switch_event_get_header_nil(event, "Caller-Destination-Number"),
|
||||||
|
FSPHONE_CALL_DIRECTION_OUTBOUND,
|
||||||
|
uuid);
|
||||||
|
_active_calls.insert(uuid, call);
|
||||||
|
call->setState(FSPHONE_CALL_STATE_TRYING);
|
||||||
|
emit newOutgoingCall(uuid);
|
||||||
|
}
|
||||||
|
else if (strcmp(event->subclass_name, "sofia::gateway_state") == 0)
|
||||||
|
{
|
||||||
|
QString state = switch_event_get_header_nil(event, "State");
|
||||||
|
QString gw = switch_event_get_header_nil(event, "Gateway");
|
||||||
|
if (state == "TRYING")
|
||||||
|
emit gwStateChange(gw, FSPHONE_GW_STATE_TRYING);
|
||||||
|
else if (state == "REGISTER")
|
||||||
|
emit gwStateChange(gw, FSPHONE_GW_STATE_REGISTER);
|
||||||
|
else if (state == "REGED")
|
||||||
|
emit gwStateChange(gw, FSPHONE_GW_STATE_REGED);
|
||||||
|
else if (state == "UNREGED")
|
||||||
|
emit gwStateChange(gw, FSPHONE_GW_STATE_UNREGED);
|
||||||
|
else if (state == "UNREGISTER")
|
||||||
|
emit gwStateChange(gw, FSPHONE_GW_STATE_UNREGISTER);
|
||||||
|
else if (state =="FAILED")
|
||||||
|
emit gwStateChange(gw, FSPHONE_GW_STATE_FAILED);
|
||||||
|
else if (state == "FAIL_WAIT")
|
||||||
|
emit gwStateChange(gw, FSPHONE_GW_STATE_FAIL_WAIT);
|
||||||
|
else if (state == "EXPIRED")
|
||||||
|
emit gwStateChange(gw, FSPHONE_GW_STATE_EXPIRED);
|
||||||
|
else if (state == "NOREG")
|
||||||
|
emit gwStateChange(gw, FSPHONE_GW_STATE_NOREG);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//printf("We got a not treated custom event: %s\n", (!zstr(event->subclass_name) ? event->subclass_name : "NULL"));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch_status_t FSHost::sendCmd(const char *cmd, const char *args, QString *res)
|
||||||
|
{
|
||||||
|
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||||
|
switch_stream_handle_t stream = { 0 };
|
||||||
|
SWITCH_STANDARD_STREAM(stream);
|
||||||
|
status = switch_api_execute(cmd, args, NULL, &stream);
|
||||||
|
*res = switch_str_nil((char *) stream.data);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FSHost::printEventHeaders(switch_event_t *event)
|
||||||
|
{
|
||||||
|
switch_event_header_t *hp;
|
||||||
|
printf("Received event: %s(%s)\n", switch_event_name(event->event_id), switch_event_get_header_nil(event, "Event-Subclass"));
|
||||||
|
for (hp = event->headers; hp; hp = hp->next) {
|
||||||
|
printf("%s=%s\n", hp->name, hp->value);
|
||||||
|
}
|
||||||
|
printf("\n\n");
|
||||||
|
}
|
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||||
|
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
|
||||||
|
*
|
||||||
|
* Version: MPL 1.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* Anthony Minessale II <anthm@freeswitch.org>
|
||||||
|
* Portions created by the Initial Developer are Copyright (C)
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*
|
||||||
|
* Joao Mesquita <jmesquita@freeswitch.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef FSHOST_H
|
||||||
|
#define FSHOST_H
|
||||||
|
|
||||||
|
#include <QThread>
|
||||||
|
#include <QHash>
|
||||||
|
#include <switch.h>
|
||||||
|
|
||||||
|
class Call;
|
||||||
|
|
||||||
|
#define FSPHONE_GW_STATE_TRYING 0
|
||||||
|
#define FSPHONE_GW_STATE_REGISTER 1
|
||||||
|
#define FSPHONE_GW_STATE_REGED 2
|
||||||
|
#define FSPHONE_GW_STATE_UNREGED 3
|
||||||
|
#define FSPHONE_GW_STATE_UNREGISTER 4
|
||||||
|
#define FSPHONE_GW_STATE_FAILED 5
|
||||||
|
#define FSPHONE_GW_STATE_FAIL_WAIT 6
|
||||||
|
#define FSPHONE_GW_STATE_EXPIRED 7
|
||||||
|
#define FSPHONE_GW_STATE_NOREG 8
|
||||||
|
|
||||||
|
static const char *fsphone_gw_state_names[] = {
|
||||||
|
"TRYING",
|
||||||
|
"REGISTER",
|
||||||
|
"REGED",
|
||||||
|
"UNREGED",
|
||||||
|
"UNREGISTER",
|
||||||
|
"FAILED",
|
||||||
|
"FAIL_WAIT",
|
||||||
|
"EXPIRED",
|
||||||
|
"NOREG"
|
||||||
|
};
|
||||||
|
|
||||||
|
class FSHost : public QThread
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit FSHost(QObject *parent = 0);
|
||||||
|
switch_status_t sendCmd(const char *cmd, const char *args, QString *res);
|
||||||
|
void generalEventHandler(switch_event_t *event);
|
||||||
|
Call * getCallByUUID(QString uuid) { return _active_calls.value(uuid, NULL); }
|
||||||
|
QString getGwStateName(int id) { return fsphone_gw_state_names[id]; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void run(void);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void coreLoadingError(QString);
|
||||||
|
void ready(void);
|
||||||
|
void ringing(QString);
|
||||||
|
void answered(QString);
|
||||||
|
void newOutgoingCall(QString);
|
||||||
|
void callFailed(QString);
|
||||||
|
void hungup(Call*);
|
||||||
|
void gwStateChange(QString, int);
|
||||||
|
|
||||||
|
private:
|
||||||
|
switch_status_t processBlegEvent(switch_event_t *, QString);
|
||||||
|
switch_status_t processAlegEvent(switch_event_t *, QString);
|
||||||
|
void printEventHeaders(switch_event_t *event);
|
||||||
|
QHash<QString, Call*> _active_calls;
|
||||||
|
QHash<QString, QString> _bleg_uuids;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern FSHost g_FSHost;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Used to match callback from fs core. We dup the event and call the class
|
||||||
|
method callback to make use of the signal/slot infrastructure.
|
||||||
|
*/
|
||||||
|
static void eventHandlerCallback(switch_event_t *event)
|
||||||
|
{
|
||||||
|
switch_event_t *clone = NULL;
|
||||||
|
if (switch_event_dup(&clone, event) == SWITCH_STATUS_SUCCESS) {
|
||||||
|
g_FSHost.generalEventHandler(clone);
|
||||||
|
}
|
||||||
|
switch_safe_free(clone);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FSHOST_H
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||||
|
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
|
||||||
|
*
|
||||||
|
* Version: MPL 1.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* Anthony Minessale II <anthm@freeswitch.org>
|
||||||
|
* Portions created by the Initial Developer are Copyright (C)
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*
|
||||||
|
* Joao Mesquita <jmesquita@freeswitch.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <QtGui/QApplication>
|
||||||
|
#include <QSplashScreen>
|
||||||
|
#include "mainwindow.h"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
QApplication a(argc, argv);
|
||||||
|
QCoreApplication::setOrganizationName("FreeSWITCH");
|
||||||
|
QCoreApplication::setOrganizationDomain("freeswitch.org");
|
||||||
|
QCoreApplication::setApplicationName("FSPhone");
|
||||||
|
|
||||||
|
QPixmap image(":/images/splash.png");
|
||||||
|
QSplashScreen *splash = new QSplashScreen(image);
|
||||||
|
splash->show();
|
||||||
|
splash->showMessage("Loading, please wait...", Qt::AlignRight|Qt::AlignBottom, Qt::blue);
|
||||||
|
|
||||||
|
QObject::connect(&g_FSHost, SIGNAL(ready()), splash, SLOT(close()));
|
||||||
|
MainWindow w;
|
||||||
|
QObject::connect(&g_FSHost, SIGNAL(ready()), &w, SLOT(show()));
|
||||||
|
g_FSHost.start();
|
||||||
|
return a.exec();
|
||||||
|
}
|
|
@ -0,0 +1,334 @@
|
||||||
|
/*
|
||||||
|
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||||
|
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
|
||||||
|
*
|
||||||
|
* Version: MPL 1.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* Anthony Minessale II <anthm@freeswitch.org>
|
||||||
|
* Portions created by the Initial Developer are Copyright (C)
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*
|
||||||
|
* Joao Mesquita <jmesquita@freeswitch.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <QInputDialog>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include "mainwindow.h"
|
||||||
|
#include "ui_mainwindow.h"
|
||||||
|
|
||||||
|
MainWindow::MainWindow(QWidget *parent) :
|
||||||
|
QMainWindow(parent),
|
||||||
|
ui(new Ui::MainWindow),
|
||||||
|
preferences(NULL)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
dialpadMapper = new QSignalMapper(this);
|
||||||
|
connect(ui->dtmf0Btn, SIGNAL(clicked()), dialpadMapper, SLOT(map()));
|
||||||
|
connect(ui->dtmf1Btn, SIGNAL(clicked()), dialpadMapper, SLOT(map()));
|
||||||
|
connect(ui->dtmf2Btn, SIGNAL(clicked()), dialpadMapper, SLOT(map()));
|
||||||
|
connect(ui->dtmf3Btn, SIGNAL(clicked()), dialpadMapper, SLOT(map()));
|
||||||
|
connect(ui->dtmf4Btn, SIGNAL(clicked()), dialpadMapper, SLOT(map()));
|
||||||
|
connect(ui->dtmf5Btn, SIGNAL(clicked()), dialpadMapper, SLOT(map()));
|
||||||
|
connect(ui->dtmf6Btn, SIGNAL(clicked()), dialpadMapper, SLOT(map()));
|
||||||
|
connect(ui->dtmf7Btn, SIGNAL(clicked()), dialpadMapper, SLOT(map()));
|
||||||
|
connect(ui->dtmf8Btn, SIGNAL(clicked()), dialpadMapper, SLOT(map()));
|
||||||
|
connect(ui->dtmf9Btn, SIGNAL(clicked()), dialpadMapper, SLOT(map()));
|
||||||
|
connect(ui->dtmfABtn, SIGNAL(clicked()), dialpadMapper, SLOT(map()));
|
||||||
|
connect(ui->dtmfBBtn, SIGNAL(clicked()), dialpadMapper, SLOT(map()));
|
||||||
|
connect(ui->dtmfCBtn, SIGNAL(clicked()), dialpadMapper, SLOT(map()));
|
||||||
|
connect(ui->dtmfDBtn, SIGNAL(clicked()), dialpadMapper, SLOT(map()));
|
||||||
|
connect(ui->dtmfAstBtn, SIGNAL(clicked()), dialpadMapper, SLOT(map()));
|
||||||
|
connect(ui->dtmfPoundBtn, SIGNAL(clicked()), dialpadMapper, SLOT(map()));
|
||||||
|
dialpadMapper->setMapping(ui->dtmf0Btn, QString("0"));
|
||||||
|
dialpadMapper->setMapping(ui->dtmf1Btn, QString("1"));
|
||||||
|
dialpadMapper->setMapping(ui->dtmf2Btn, QString("2"));
|
||||||
|
dialpadMapper->setMapping(ui->dtmf3Btn, QString("3"));
|
||||||
|
dialpadMapper->setMapping(ui->dtmf4Btn, QString("4"));
|
||||||
|
dialpadMapper->setMapping(ui->dtmf5Btn, QString("5"));
|
||||||
|
dialpadMapper->setMapping(ui->dtmf6Btn, QString("6"));
|
||||||
|
dialpadMapper->setMapping(ui->dtmf7Btn, QString("7"));
|
||||||
|
dialpadMapper->setMapping(ui->dtmf8Btn, QString("8"));
|
||||||
|
dialpadMapper->setMapping(ui->dtmf9Btn, QString("9"));
|
||||||
|
dialpadMapper->setMapping(ui->dtmfABtn, QString("A"));
|
||||||
|
dialpadMapper->setMapping(ui->dtmfBBtn, QString("B"));
|
||||||
|
dialpadMapper->setMapping(ui->dtmfCBtn, QString("C"));
|
||||||
|
dialpadMapper->setMapping(ui->dtmfDBtn, QString("D"));
|
||||||
|
dialpadMapper->setMapping(ui->dtmfAstBtn, QString("*"));
|
||||||
|
dialpadMapper->setMapping(ui->dtmfPoundBtn, QString("#"));
|
||||||
|
connect(dialpadMapper, SIGNAL(mapped(QString)), this, SLOT(dialDTMF(QString)));
|
||||||
|
|
||||||
|
connect(&g_FSHost, SIGNAL(ready()),this, SLOT(fshostReady()));
|
||||||
|
connect(&g_FSHost, SIGNAL(ringing(QString)), this, SLOT(ringing(QString)));
|
||||||
|
connect(&g_FSHost, SIGNAL(answered(QString)), this, SLOT(answered(QString)));
|
||||||
|
connect(&g_FSHost, SIGNAL(hungup(Call*)), this, SLOT(hungup(Call*)));
|
||||||
|
connect(&g_FSHost, SIGNAL(newOutgoingCall(QString)), this, SLOT(newOutgoingCall(QString)));
|
||||||
|
connect(&g_FSHost, SIGNAL(gwStateChange(QString,int)), this, SLOT(gwStateChanged(QString,int)));
|
||||||
|
/*connect(&g_FSHost, SIGNAL(coreLoadingError(QString)), this, SLOT(coreLoadingError(QString)));*/
|
||||||
|
|
||||||
|
connect(ui->newCallBtn, SIGNAL(clicked()), this, SLOT(makeCall()));
|
||||||
|
connect(ui->answerBtn, SIGNAL(clicked()), this, SLOT(paAnswer()));
|
||||||
|
connect(ui->hangupBtn, SIGNAL(clicked()), this, SLOT(paHangup()));
|
||||||
|
connect(ui->listCalls, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(callListDoubleClick(QListWidgetItem*)));
|
||||||
|
connect(ui->action_Preferences, SIGNAL(triggered()), this, SLOT(prefTriggered()));
|
||||||
|
connect(ui->action_Exit, SIGNAL(triggered()), this, SLOT(close()));
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWindow::~MainWindow()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
QString res;
|
||||||
|
g_FSHost.sendCmd("fsctl", "shutdown", &res);
|
||||||
|
g_FSHost.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::prefTriggered()
|
||||||
|
{
|
||||||
|
if (!preferences)
|
||||||
|
preferences = new PrefDialog();
|
||||||
|
|
||||||
|
preferences->raise();
|
||||||
|
preferences->show();
|
||||||
|
preferences->activateWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::coreLoadingError(QString err)
|
||||||
|
{
|
||||||
|
QMessageBox::warning(this, "Error Loading Core...", err, QMessageBox::Ok);
|
||||||
|
QApplication::exit(255);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::gwStateChanged(QString gw, int state)
|
||||||
|
{
|
||||||
|
ui->statusBar->showMessage(tr("Account %1 is %2").arg(gw, g_FSHost.getGwStateName(state)));
|
||||||
|
|
||||||
|
/* TODO: This should be placed somewhere else when the config handler is here... */
|
||||||
|
QList<QTableWidgetItem *> match = ui->tableAccounts->findItems(gw, Qt::MatchExactly);
|
||||||
|
if (match.isEmpty())
|
||||||
|
{
|
||||||
|
/* Create the damn thing */
|
||||||
|
ui->tableAccounts->setRowCount(ui->tableAccounts->rowCount()+1);
|
||||||
|
QTableWidgetItem *gwField = new QTableWidgetItem(gw);
|
||||||
|
QTableWidgetItem *stField = new QTableWidgetItem(g_FSHost.getGwStateName(state));
|
||||||
|
ui->tableAccounts->setItem(0,0,gwField);
|
||||||
|
ui->tableAccounts->setItem(0,1,stField);
|
||||||
|
ui->tableAccounts->resizeColumnsToContents();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTableWidgetItem *gwField = match.at(0);
|
||||||
|
QTableWidgetItem *stField = ui->tableAccounts->item(gwField->row(),1);
|
||||||
|
stField->setText(g_FSHost.getGwStateName(state));
|
||||||
|
ui->tableAccounts->resizeColumnsToContents();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::dialDTMF(QString dtmf)
|
||||||
|
{
|
||||||
|
QString result;
|
||||||
|
QString dtmf_string = QString("dtmf %1").arg(dtmf);
|
||||||
|
if (g_FSHost.sendCmd("pa", dtmf_string.toAscii(), &result) == SWITCH_STATUS_FALSE) {
|
||||||
|
ui->textEdit->setText("Error sending that command");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::callListDoubleClick(QListWidgetItem *item)
|
||||||
|
{
|
||||||
|
Call *call = g_FSHost.getCallByUUID(item->data(Qt::UserRole).toString());
|
||||||
|
QString switch_str = QString("switch %1").arg(call->getCallID());
|
||||||
|
QString result;
|
||||||
|
if (g_FSHost.sendCmd("pa", switch_str.toAscii(), &result) == SWITCH_STATUS_FALSE) {
|
||||||
|
ui->textEdit->setText(QString("Error switching to call %1").arg(call->getCallID()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ui->hangupBtn->setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::makeCall()
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
QString dialstring = QInputDialog::getText(this, tr("Make new call"),
|
||||||
|
tr("Number to dial:"), QLineEdit::Normal, NULL,&ok);
|
||||||
|
|
||||||
|
if (ok && !dialstring.isEmpty())
|
||||||
|
{
|
||||||
|
paCall(dialstring);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::fshostReady()
|
||||||
|
{
|
||||||
|
ui->statusBar->showMessage("Ready");
|
||||||
|
ui->newCallBtn->setEnabled(true);
|
||||||
|
ui->textEdit->setEnabled(true);
|
||||||
|
ui->textEdit->setText("Ready to dial and receive calls!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::paAnswer()
|
||||||
|
{
|
||||||
|
QString result;
|
||||||
|
if (g_FSHost.sendCmd("pa", "answer", &result) == SWITCH_STATUS_FALSE) {
|
||||||
|
ui->textEdit->setText("Error sending that command");
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->textEdit->setText("Talking...");
|
||||||
|
ui->hangupBtn->setEnabled(true);
|
||||||
|
ui->answerBtn->setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::paCall(QString dialstring)
|
||||||
|
{
|
||||||
|
QString result;
|
||||||
|
|
||||||
|
QString callstring = QString("call %1").arg(dialstring);
|
||||||
|
|
||||||
|
if (g_FSHost.sendCmd("pa", callstring.toAscii(), &result) == SWITCH_STATUS_FALSE) {
|
||||||
|
ui->textEdit->setText("Error sending that command");
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->hangupBtn->setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::paHangup()
|
||||||
|
{
|
||||||
|
QString result;
|
||||||
|
if (g_FSHost.sendCmd("pa", "hangup", &result) == SWITCH_STATUS_FALSE) {
|
||||||
|
ui->textEdit->setText("Error sending that command");
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->textEdit->setText("Click to dial number...");
|
||||||
|
ui->statusBar->showMessage("Call hungup");
|
||||||
|
ui->hangupBtn->setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::newOutgoingCall(QString uuid)
|
||||||
|
{
|
||||||
|
Call *call = g_FSHost.getCallByUUID(uuid);
|
||||||
|
ui->textEdit->setText(QString("Calling %1 (%2)").arg(call->getCidName(), call->getCidNumber()));
|
||||||
|
QListWidgetItem *item = new QListWidgetItem(tr("%1 (%2) - Calling").arg(call->getCidName(), call->getCidNumber()));
|
||||||
|
item->setData(Qt::UserRole, uuid);
|
||||||
|
ui->listCalls->addItem(item);
|
||||||
|
ui->hangupBtn->setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::ringing(QString uuid)
|
||||||
|
{
|
||||||
|
|
||||||
|
Call *call = g_FSHost.getCallByUUID(uuid);
|
||||||
|
for (int i=0; i<ui->listCalls->count(); i++)
|
||||||
|
{
|
||||||
|
QListWidgetItem *item = ui->listCalls->item(i);
|
||||||
|
if (item->data(Qt::UserRole).toString() == uuid)
|
||||||
|
{
|
||||||
|
item->setText(tr("%1 - Ringing").arg(call->getCidNumber()));
|
||||||
|
ui->textEdit->setText(QString("Call from %1 (%2)").arg(call->getCidName(), call->getCidNumber()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->textEdit->setText(QString("Call from %1 (%2)").arg(call->getCidName(), call->getCidNumber()));
|
||||||
|
QListWidgetItem *item = new QListWidgetItem(tr("%1 (%2) - Ringing").arg(call->getCidName(), call->getCidNumber()));
|
||||||
|
item->setData(Qt::UserRole, uuid);
|
||||||
|
ui->listCalls->addItem(item);
|
||||||
|
ui->answerBtn->setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::answered(QString uuid)
|
||||||
|
{
|
||||||
|
Call *call = g_FSHost.getCallByUUID(uuid);
|
||||||
|
for (int i=0; i<ui->listCalls->count(); i++)
|
||||||
|
{
|
||||||
|
QListWidgetItem *item = ui->listCalls->item(i);
|
||||||
|
if (item->data(Qt::UserRole).toString() == uuid)
|
||||||
|
{
|
||||||
|
if (call->getDirection() == FSPHONE_CALL_DIRECTION_INBOUND)
|
||||||
|
{
|
||||||
|
item->setText(tr("%1 (%2) - Active").arg(call->getCidName(), call->getCidNumber()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item->setText(tr("%1 - Active").arg(call->getCidNumber()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ui->dtmf0Btn->setEnabled(true);
|
||||||
|
ui->dtmf1Btn->setEnabled(true);
|
||||||
|
ui->dtmf2Btn->setEnabled(true);
|
||||||
|
ui->dtmf3Btn->setEnabled(true);
|
||||||
|
ui->dtmf4Btn->setEnabled(true);
|
||||||
|
ui->dtmf5Btn->setEnabled(true);
|
||||||
|
ui->dtmf6Btn->setEnabled(true);
|
||||||
|
ui->dtmf7Btn->setEnabled(true);
|
||||||
|
ui->dtmf8Btn->setEnabled(true);
|
||||||
|
ui->dtmf9Btn->setEnabled(true);
|
||||||
|
ui->dtmfABtn->setEnabled(true);
|
||||||
|
ui->dtmfBBtn->setEnabled(true);
|
||||||
|
ui->dtmfCBtn->setEnabled(true);
|
||||||
|
ui->dtmfDBtn->setEnabled(true);
|
||||||
|
ui->dtmfAstBtn->setEnabled(true);
|
||||||
|
ui->dtmfPoundBtn->setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::hungup(Call* call)
|
||||||
|
{
|
||||||
|
for (int i=0; i<ui->listCalls->count(); i++)
|
||||||
|
{
|
||||||
|
QListWidgetItem *item = ui->listCalls->item(i);
|
||||||
|
if (item->data(Qt::UserRole).toString() == call->getUUID())
|
||||||
|
{
|
||||||
|
delete ui->listCalls->takeItem(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ui->textEdit->setText(tr("Call with %1 (%2) hungup.").arg(call->getCidName(), call->getCidNumber()));
|
||||||
|
/* TODO: Will cause problems if 2 calls are received at the same time */
|
||||||
|
ui->answerBtn->setEnabled(false);
|
||||||
|
ui->hangupBtn->setEnabled(false);
|
||||||
|
ui->dtmf0Btn->setEnabled(false);
|
||||||
|
ui->dtmf1Btn->setEnabled(false);
|
||||||
|
ui->dtmf2Btn->setEnabled(false);
|
||||||
|
ui->dtmf3Btn->setEnabled(false);
|
||||||
|
ui->dtmf4Btn->setEnabled(false);
|
||||||
|
ui->dtmf5Btn->setEnabled(false);
|
||||||
|
ui->dtmf6Btn->setEnabled(false);
|
||||||
|
ui->dtmf7Btn->setEnabled(false);
|
||||||
|
ui->dtmf8Btn->setEnabled(false);
|
||||||
|
ui->dtmf9Btn->setEnabled(false);
|
||||||
|
ui->dtmfABtn->setEnabled(false);
|
||||||
|
ui->dtmfBBtn->setEnabled(false);
|
||||||
|
ui->dtmfCBtn->setEnabled(false);
|
||||||
|
ui->dtmfDBtn->setEnabled(false);
|
||||||
|
ui->dtmfAstBtn->setEnabled(false);
|
||||||
|
ui->dtmfPoundBtn->setEnabled(false);
|
||||||
|
delete call;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::changeEvent(QEvent *e)
|
||||||
|
{
|
||||||
|
QMainWindow::changeEvent(e);
|
||||||
|
switch (e->type()) {
|
||||||
|
case QEvent::LanguageChange:
|
||||||
|
ui->retranslateUi(this);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||||
|
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
|
||||||
|
*
|
||||||
|
* Version: MPL 1.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* Anthony Minessale II <anthm@freeswitch.org>
|
||||||
|
* Portions created by the Initial Developer are Copyright (C)
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*
|
||||||
|
* Joao Mesquita <jmesquita@freeswitch.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef MAINWINDOW_H
|
||||||
|
#define MAINWINDOW_H
|
||||||
|
|
||||||
|
#include <QMainWindow>
|
||||||
|
#include <QListWidgetItem>
|
||||||
|
#include <QSignalMapper>
|
||||||
|
#include <switch.h>
|
||||||
|
#include <fshost.h>
|
||||||
|
#include <call.h>
|
||||||
|
#include <prefdialog.h>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class MainWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
class MainWindow : public QMainWindow {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
MainWindow(QWidget *parent = 0);
|
||||||
|
~MainWindow();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void changeEvent(QEvent *e);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void dtmfDialed(QString);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void prefTriggered();
|
||||||
|
void coreLoadingError(QString);
|
||||||
|
void gwStateChanged(QString, int);
|
||||||
|
void dialDTMF(QString);
|
||||||
|
void callListDoubleClick(QListWidgetItem *);
|
||||||
|
void makeCall();
|
||||||
|
void fshostReady();
|
||||||
|
void paAnswer();
|
||||||
|
void paCall(QString);
|
||||||
|
void paHangup();
|
||||||
|
void newOutgoingCall(QString);
|
||||||
|
void ringing(QString);
|
||||||
|
void answered(QString);
|
||||||
|
void hungup(Call*);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::MainWindow *ui;
|
||||||
|
QSignalMapper *dialpadMapper;
|
||||||
|
PrefDialog *preferences;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MAINWINDOW_H
|
|
@ -0,0 +1,350 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>MainWindow</class>
|
||||||
|
<widget class="QMainWindow" name="MainWindow">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>580</width>
|
||||||
|
<height>563</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>FSPhone - A FreeSWITCH softphone</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="centralWidget">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QTextEdit" name="textEdit">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="newCallBtn">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>New Call</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QPushButton" name="answerBtn">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Answer</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QPushButton" name="hangupBtn">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Hangup</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QPushButton" name="dtmf1Btn">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>1</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QPushButton" name="dtmf2Btn">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>2</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="2">
|
||||||
|
<widget class="QPushButton" name="dtmf3Btn">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>3</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QPushButton" name="dtmf4Btn">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>4</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QPushButton" name="dtmf5Btn">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>5</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="2">
|
||||||
|
<widget class="QPushButton" name="dtmf6Btn">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>6</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QPushButton" name="dtmf7Btn">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>7</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QPushButton" name="dtmf8Btn">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>8</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="2">
|
||||||
|
<widget class="QPushButton" name="dtmf9Btn">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>9</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QPushButton" name="dtmfAstBtn">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>*</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QPushButton" name="dtmf0Btn">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>0</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="2">
|
||||||
|
<widget class="QPushButton" name="dtmfPoundBtn">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>#</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="3">
|
||||||
|
<widget class="QPushButton" name="dtmfABtn">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>A</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="3">
|
||||||
|
<widget class="QPushButton" name="dtmfBBtn">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>B</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="3">
|
||||||
|
<widget class="QPushButton" name="dtmfDBtn">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>D</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="3">
|
||||||
|
<widget class="QPushButton" name="dtmfCBtn">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>C</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>Active Calls</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QListWidget" name="listCalls"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_2">
|
||||||
|
<property name="title">
|
||||||
|
<string>Active Accounts</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QTableWidget" name="tableAccounts">
|
||||||
|
<property name="editTriggers">
|
||||||
|
<set>QAbstractItemView::NoEditTriggers</set>
|
||||||
|
</property>
|
||||||
|
<property name="alternatingRowColors">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="selectionMode">
|
||||||
|
<enum>QAbstractItemView::NoSelection</enum>
|
||||||
|
</property>
|
||||||
|
<property name="selectionBehavior">
|
||||||
|
<enum>QAbstractItemView::SelectRows</enum>
|
||||||
|
</property>
|
||||||
|
<property name="showGrid">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="cornerButtonEnabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="rowCount">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<attribute name="horizontalHeaderVisible">
|
||||||
|
<bool>true</bool>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="horizontalHeaderCascadingSectionResizes">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="verticalHeaderVisible">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="verticalHeaderHighlightSections">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Account</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Status</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QMenuBar" name="menuBar">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>580</width>
|
||||||
|
<height>22</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<widget class="QMenu" name="menu_File">
|
||||||
|
<property name="title">
|
||||||
|
<string>&File</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="action_Preferences"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
|
<addaction name="action_Exit"/>
|
||||||
|
</widget>
|
||||||
|
<addaction name="menu_File"/>
|
||||||
|
</widget>
|
||||||
|
<widget class="QToolBar" name="mainToolBar">
|
||||||
|
<attribute name="toolBarArea">
|
||||||
|
<enum>TopToolBarArea</enum>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="toolBarBreak">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
<widget class="QStatusBar" name="statusBar"/>
|
||||||
|
<action name="action_Preferences">
|
||||||
|
<property name="text">
|
||||||
|
<string>&Preferences</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="action_Exit">
|
||||||
|
<property name="text">
|
||||||
|
<string>&Exit</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
</widget>
|
||||||
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -0,0 +1,149 @@
|
||||||
|
/*
|
||||||
|
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||||
|
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
|
||||||
|
*
|
||||||
|
* Version: MPL 1.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* Anthony Minessale II <anthm@freeswitch.org>
|
||||||
|
* Portions created by the Initial Developer are Copyright (C)
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*
|
||||||
|
* Joao Mesquita <jmesquita@freeswitch.org>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Module to load configurations from Qt preference system QSettings
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include <QString>
|
||||||
|
#include <QtGui>
|
||||||
|
#include <QDir>
|
||||||
|
#include "mod_qsettings/mod_qsettings.h"
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
switch_memory_pool_t* pool;
|
||||||
|
} globals;
|
||||||
|
|
||||||
|
switch_xml_t XMLBinding::getConfigXML(QString tmpl)
|
||||||
|
{
|
||||||
|
switch_event_t *e;
|
||||||
|
switch_event_create_plain(&e, SWITCH_EVENT_REQUEST_PARAMS);
|
||||||
|
switch_assert(e);
|
||||||
|
|
||||||
|
QFile tmplFile(QString("%1/templates/%2.xml").arg(QApplication::applicationDirPath(),tmpl));
|
||||||
|
|
||||||
|
if (!tmplFile.exists()) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
|
||||||
|
"Template %s.xml, doesn't exist on directory, falling back to embedded template.\n",
|
||||||
|
tmpl.toAscii().constData());
|
||||||
|
tmplFile.setFileName(QString(":/confs/%1.xml").arg(tmpl));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tmplFile.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||||
|
{
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Template %s could not be read.!\n", tmpl.toAscii().constData());
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open template file and expand all strings based on QSettings */
|
||||||
|
QString tmplContents(tmplFile.readAll());
|
||||||
|
tmplFile.close();
|
||||||
|
_settings->beginGroup("FreeSIWTCH/conf");
|
||||||
|
_settings->beginGroup(tmpl);
|
||||||
|
foreach(QString k, _settings->childKeys())
|
||||||
|
{
|
||||||
|
switch_event_add_header_string(e, SWITCH_STACK_BOTTOM, k.toAscii().constData(), _settings->value(k).toByteArray().constData());
|
||||||
|
}
|
||||||
|
|
||||||
|
char *res = switch_event_expand_headers(e, tmplContents.toAscii().constData());
|
||||||
|
switch_safe_free(e);
|
||||||
|
return switch_xml_parse_str(res, strlen(res));
|
||||||
|
}
|
||||||
|
|
||||||
|
static switch_xml_t xml_url_fetch(const char *section, const char *tag_name, const char *key_name, const char *key_value, switch_event_t *params,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
XMLBinding *binding = (XMLBinding *) user_data;
|
||||||
|
|
||||||
|
if (!binding) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return binding->getConfigXML(key_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static switch_status_t do_config(void)
|
||||||
|
{
|
||||||
|
char *cf = "qsettings.conf";
|
||||||
|
switch_xml_t cfg, xml, bindings_tag;
|
||||||
|
XMLBinding *binding = NULL;
|
||||||
|
|
||||||
|
if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", cf);
|
||||||
|
return SWITCH_STATUS_TERM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(bindings_tag = switch_xml_child(cfg, "bindings"))) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing <bindings> tag!\n");
|
||||||
|
switch_xml_free(xml);
|
||||||
|
return SWITCH_STATUS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString bind_mask = switch_xml_attr_soft(bindings_tag, "value");
|
||||||
|
if (!bind_mask.isEmpty())
|
||||||
|
{
|
||||||
|
binding = new XMLBinding(bind_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Binding XML Fetch Function [%s]\n",
|
||||||
|
binding->getBinding().isEmpty() ? "all" : binding->getBinding().toAscii().constData());
|
||||||
|
switch_xml_bind_search_function(xml_url_fetch, switch_xml_parse_section_string(binding->getBinding().toAscii().constData()), binding);
|
||||||
|
binding = NULL;
|
||||||
|
|
||||||
|
switch_xml_free(xml);
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
SWITCH_MODULE_LOAD_FUNCTION(mod_qsettings_load)
|
||||||
|
{
|
||||||
|
/*switch_api_interface_t *qsettings_api_interface;*/
|
||||||
|
|
||||||
|
/* connect my internal structure to the blank pointer passed to me */
|
||||||
|
*module_interface = switch_loadable_module_create_module_interface(pool, "mod_qsettings");
|
||||||
|
|
||||||
|
memset(&globals,0,sizeof(globals));
|
||||||
|
globals.pool = pool;
|
||||||
|
|
||||||
|
if (do_config() == SWITCH_STATUS_SUCCESS) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Sucessfully configured.\n");
|
||||||
|
} else {
|
||||||
|
return SWITCH_STATUS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "We loaded mod_qsettings.\n");
|
||||||
|
/* indicate that the module should continue to be loaded */
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_qsettings_shutdown)
|
||||||
|
{
|
||||||
|
switch_xml_unbind_search_function_ptr(xml_url_fetch);
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||||
|
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
|
||||||
|
*
|
||||||
|
* Version: MPL 1.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* Anthony Minessale II <anthm@freeswitch.org>
|
||||||
|
* Portions created by the Initial Developer are Copyright (C)
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*
|
||||||
|
* Joao Mesquita <jmesquita@freeswitch.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MOD_QSETTINGS_H
|
||||||
|
#define MOD_QSETTINGS_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QSettings>
|
||||||
|
#include <switch.h>
|
||||||
|
|
||||||
|
SWITCH_MODULE_LOAD_FUNCTION(mod_qsettings_load);
|
||||||
|
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_qsettings_shutdown);
|
||||||
|
|
||||||
|
class XMLBinding
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
XMLBinding(QString binding) : _binding(binding), _settings(new QSettings) {}
|
||||||
|
QString getBinding(void) { return _binding; }
|
||||||
|
switch_xml_t getConfigXML(QString);
|
||||||
|
private:
|
||||||
|
QString _binding;
|
||||||
|
QSettings* _settings;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MOD_QSETTINGS_H
|
|
@ -0,0 +1,132 @@
|
||||||
|
#include <QtGui>
|
||||||
|
#include "prefdialog.h"
|
||||||
|
#include "ui_prefdialog.h"
|
||||||
|
|
||||||
|
PrefDialog::PrefDialog(QWidget *parent) :
|
||||||
|
QDialog(parent),
|
||||||
|
ui(new Ui::PrefDialog)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
getPaDevlist();
|
||||||
|
}
|
||||||
|
|
||||||
|
PrefDialog::~PrefDialog()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrefDialog::getPaDevlist()
|
||||||
|
{
|
||||||
|
QString result;
|
||||||
|
int errorLine, errorColumn;
|
||||||
|
QString errorMsg;
|
||||||
|
|
||||||
|
if (g_FSHost.sendCmd("pa", "devlist xml", &result) != SWITCH_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
QMessageBox::critical(this, tr("PortAudio error" ),
|
||||||
|
tr("Error querying audio devices."),
|
||||||
|
QMessageBox::Ok);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_xmlPaDevList.setContent(result, &errorMsg, &errorLine, &errorColumn))
|
||||||
|
{
|
||||||
|
QMessageBox::critical(this, tr("PortAudio error" ),
|
||||||
|
tr("Error parsing output xml from pa devlist.\n%1 (Line:%2, Col:%3).").arg(errorMsg,
|
||||||
|
errorLine,
|
||||||
|
errorColumn),
|
||||||
|
QMessageBox::Ok);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QDomElement root = _xmlPaDevList.documentElement();
|
||||||
|
if (root.tagName() != "xml")
|
||||||
|
{
|
||||||
|
QMessageBox::critical(this, tr("PortAudio error" ),
|
||||||
|
tr("Error parsing output xml from pa devlist. Root tag is not <xml>."),
|
||||||
|
QMessageBox::Ok);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QDomElement devices = root.firstChildElement("devices");
|
||||||
|
if (devices.isNull())
|
||||||
|
{
|
||||||
|
QMessageBox::critical(this, tr("PortAudio error" ),
|
||||||
|
tr("Error parsing output xml from pa devlist. There is no <devices> tag."),
|
||||||
|
QMessageBox::Ok);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDomElement child = devices.firstChildElement();
|
||||||
|
if (child.isNull())
|
||||||
|
{
|
||||||
|
QMessageBox::critical(this, tr("PortAudio error" ),
|
||||||
|
tr("Error parsing output xml from pa devlist. There is no <device> tag."),
|
||||||
|
QMessageBox::Ok);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!child.isNull())
|
||||||
|
{
|
||||||
|
if (child.tagName() == "device")
|
||||||
|
{
|
||||||
|
QString id, name, inputs, outputs;
|
||||||
|
id = child.attribute("id","-1");
|
||||||
|
name = child.attribute("name","Null");
|
||||||
|
inputs = child.attribute("inputs","0");
|
||||||
|
outputs = child.attribute("outputs","0");
|
||||||
|
if (inputs.toInt() != 0)
|
||||||
|
ui->PaIndevCombo->addItem(name,inputs.toInt());
|
||||||
|
if (outputs.toInt() != 0)
|
||||||
|
{
|
||||||
|
ui->PaOutdevCombo->addItem(name,inputs.toInt());
|
||||||
|
ui->PaRingdevCombo->addItem(name,inputs.toInt());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
child = child.nextSiblingElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
QDomElement bindings = root.firstChildElement("bindings");
|
||||||
|
if (bindings.isNull())
|
||||||
|
{
|
||||||
|
QMessageBox::critical(this, tr("PortAudio error" ),
|
||||||
|
tr("Error parsing output xml from pa devlist. There is no <bindings> tag."),
|
||||||
|
QMessageBox::Ok);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
child = devices.firstChildElement();
|
||||||
|
if (child.isNull())
|
||||||
|
{
|
||||||
|
QMessageBox::critical(this, tr("PortAudio error" ),
|
||||||
|
tr("Error parsing output xml from pa devlist. There are no bindings."),
|
||||||
|
QMessageBox::Ok);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!child.isNull())
|
||||||
|
{
|
||||||
|
QString id;
|
||||||
|
id = child.attribute("device","-1");
|
||||||
|
|
||||||
|
if (child.tagName() == "ring")
|
||||||
|
ui->PaRingdevCombo->setCurrentIndex(id.toInt());
|
||||||
|
else if (child.tagName() == "input")
|
||||||
|
ui->PaIndevCombo->setCurrentIndex(id.toInt());
|
||||||
|
else if (child.tagName() == "ring")
|
||||||
|
ui->PaOutdevCombo->setCurrentIndex(id.toInt());
|
||||||
|
|
||||||
|
child = child.nextSiblingElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrefDialog::changeEvent(QEvent *e)
|
||||||
|
{
|
||||||
|
QDialog::changeEvent(e);
|
||||||
|
switch (e->type()) {
|
||||||
|
case QEvent::LanguageChange:
|
||||||
|
ui->retranslateUi(this);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
#ifndef PREFDIALOG_H
|
||||||
|
#define PREFDIALOG_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QDomDocument>
|
||||||
|
#include <fshost.h>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class PrefDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
class PrefDialog : public QDialog {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
PrefDialog(QWidget *parent = 0);
|
||||||
|
~PrefDialog();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void changeEvent(QEvent *e);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void getPaDevlist(void);
|
||||||
|
Ui::PrefDialog *ui;
|
||||||
|
QDomDocument _xmlPaDevList;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PREFDIALOG_H
|
|
@ -0,0 +1,376 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>PrefDialog</class>
|
||||||
|
<widget class="QDialog" name="PrefDialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>477</width>
|
||||||
|
<height>356</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Preferences</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QListWidget" name="listSections">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>120</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>120</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="showDropIndicator" stdset="0">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="dragDropMode">
|
||||||
|
<enum>QAbstractItemView::NoDragDrop</enum>
|
||||||
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>96</width>
|
||||||
|
<height>84</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="movement">
|
||||||
|
<enum>QListView::Static</enum>
|
||||||
|
</property>
|
||||||
|
<property name="flow">
|
||||||
|
<enum>QListView::LeftToRight</enum>
|
||||||
|
</property>
|
||||||
|
<property name="isWrapping" stdset="0">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="spacing">
|
||||||
|
<number>12</number>
|
||||||
|
</property>
|
||||||
|
<property name="viewMode">
|
||||||
|
<enum>QListView::IconMode</enum>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Sofia</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="resources.qrc">
|
||||||
|
<normaloff>:/images/pref_sip.png</normaloff>:/images/pref_sip.png</iconset>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>PortAudio</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="resources.qrc">
|
||||||
|
<normaloff>:/images/pref_audio.gif</normaloff>:/images/pref_audio.gif</iconset>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QStackedWidget" name="stackedWidget">
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="page">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>Global Settings</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QFormLayout" name="formLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>log-level</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox"/>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>auto-restart</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QComboBox" name="comboBox"/>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>debug-presence</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_2"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_2">
|
||||||
|
<property name="title">
|
||||||
|
<string>Softphone Profile</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QFormLayout" name="formLayout_2">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="text">
|
||||||
|
<string>user-agent-string</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLineEdit" name="lineEdit"/>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="text">
|
||||||
|
<string>debug</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_3"/>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="text">
|
||||||
|
<string>sip-trace</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QComboBox" name="comboBox_2"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="page_2">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_3">
|
||||||
|
<property name="title">
|
||||||
|
<string>Devices</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QLabel" name="label_7">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>72</x>
|
||||||
|
<y>34</y>
|
||||||
|
<width>34</width>
|
||||||
|
<height>17</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>indev</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QComboBox" name="PaIndevCombo">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>111</x>
|
||||||
|
<y>32</y>
|
||||||
|
<width>111</width>
|
||||||
|
<height>26</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="label_8">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>63</x>
|
||||||
|
<y>64</y>
|
||||||
|
<width>43</width>
|
||||||
|
<height>17</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>outdev</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QComboBox" name="PaOutdevCombo">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>111</x>
|
||||||
|
<y>62</y>
|
||||||
|
<width>111</width>
|
||||||
|
<height>26</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="label_9">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>59</x>
|
||||||
|
<y>94</y>
|
||||||
|
<width>47</width>
|
||||||
|
<height>17</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>rindgev</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QComboBox" name="PaRingdevCombo">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>111</x>
|
||||||
|
<y>92</y>
|
||||||
|
<width>111</width>
|
||||||
|
<height>26</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_4">
|
||||||
|
<property name="title">
|
||||||
|
<string>Files</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QFormLayout" name="formLayout_3">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_10">
|
||||||
|
<property name="text">
|
||||||
|
<string>ring-file</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLineEdit" name="lineEdit_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>tone_stream://%(2000,4000,440.0,480.0);loops=20</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_12">
|
||||||
|
<property name="text">
|
||||||
|
<string>ring-interval</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_4"/>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_11">
|
||||||
|
<property name="text">
|
||||||
|
<string>hold-file</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QLineEdit" name="lineEdit_3"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources>
|
||||||
|
<include location="resources.qrc"/>
|
||||||
|
</resources>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>PrefDialog</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>544</x>
|
||||||
|
<y>224</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>157</x>
|
||||||
|
<y>246</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>PrefDialog</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>544</x>
|
||||||
|
<y>230</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>286</x>
|
||||||
|
<y>246</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>listSections</sender>
|
||||||
|
<signal>currentRowChanged(int)</signal>
|
||||||
|
<receiver>stackedWidget</receiver>
|
||||||
|
<slot>setCurrentIndex(int)</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>180</x>
|
||||||
|
<y>83</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>524</x>
|
||||||
|
<y>102</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<RCC>
|
||||||
|
<qresource prefix="/images">
|
||||||
|
<file alias="splash.png">resources/splash.png</file>
|
||||||
|
<file alias="pref_sip.png">resources/pref_sip.png</file>
|
||||||
|
<file alias="pref_audio.gif">resources/pref_audio.gif</file>
|
||||||
|
</qresource>
|
||||||
|
<qresource prefix="/confs">
|
||||||
|
<file alias="freeswitch.xml">conf/freeswitch.xml</file>
|
||||||
|
<file alias="example.xml">conf/accounts/example.xml</file>
|
||||||
|
<file alias="event_socket.conf.xml">conf/event_socket.conf.xml</file>
|
||||||
|
<file alias="portaudio.conf.xml">conf/portaudio.conf.xml</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
Binary file not shown.
After Width: | Height: | Size: 6.3 KiB |
Loading…
Reference in New Issue