2005-07-04 22:04:47 +00:00
|
|
|
/**
|
|
|
|
* Client.cpp
|
|
|
|
* This file is part of the YATE Project http://YATE.null.ro
|
|
|
|
*
|
|
|
|
* Yet Another Telephony Engine - a fully featured software PBX and IVR
|
|
|
|
* Copyright (C) 2004, 2005 Null Team
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include "yatecbase.h"
|
|
|
|
|
2005-07-27 18:31:47 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
|
2005-07-04 22:04:47 +00:00
|
|
|
using namespace TelEngine;
|
|
|
|
|
|
|
|
class UIHandler : public MessageHandler
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
UIHandler()
|
|
|
|
: MessageHandler("ui.action",150)
|
|
|
|
{ }
|
|
|
|
virtual bool received(Message &msg);
|
|
|
|
};
|
|
|
|
|
2006-01-30 20:44:03 +00:00
|
|
|
class UICdrHandler : public MessageHandler
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
UICdrHandler()
|
|
|
|
: MessageHandler("call.cdr",90)
|
|
|
|
{ }
|
|
|
|
virtual bool received(Message &msg);
|
|
|
|
};
|
|
|
|
|
2006-04-08 18:03:28 +00:00
|
|
|
class UIUserHandler : public MessageHandler
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
UIUserHandler()
|
|
|
|
: MessageHandler("user.login",50)
|
|
|
|
{ }
|
|
|
|
virtual bool received(Message &msg);
|
|
|
|
};
|
|
|
|
|
2005-08-13 02:02:55 +00:00
|
|
|
class ClientThreadProxy
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
enum {
|
|
|
|
setVisible,
|
|
|
|
openPopup,
|
|
|
|
hasElement,
|
|
|
|
setShow,
|
|
|
|
setText,
|
|
|
|
setActive,
|
|
|
|
setCheck,
|
|
|
|
setSelect,
|
|
|
|
setUrgent,
|
2006-04-08 18:03:28 +00:00
|
|
|
hasOption,
|
2005-08-13 02:02:55 +00:00
|
|
|
addOption,
|
|
|
|
delOption,
|
2006-01-30 20:44:03 +00:00
|
|
|
addTableRow,
|
|
|
|
delTableRow,
|
|
|
|
setTableRow,
|
2006-04-08 18:03:28 +00:00
|
|
|
getTableRow,
|
|
|
|
clearTable,
|
2005-08-13 02:02:55 +00:00
|
|
|
getText,
|
|
|
|
getCheck,
|
|
|
|
getSelect,
|
|
|
|
};
|
|
|
|
ClientThreadProxy(int func, const String& name, bool show, Window* wnd = 0, Window* skip = 0);
|
2006-01-30 20:44:03 +00:00
|
|
|
ClientThreadProxy(int func, const String& name, const String& text, Window* wnd, Window* skip);
|
|
|
|
ClientThreadProxy(int func, const String& name, const String& text, const String& item, bool show, Window* wnd, Window* skip);
|
|
|
|
ClientThreadProxy(int func, const String& name, String* rtext, bool* rbool, Window* wnd, Window* skip);
|
2005-08-13 02:02:55 +00:00
|
|
|
ClientThreadProxy(int func, const String& name, const NamedList* params, const Window* parent);
|
2006-01-30 20:44:03 +00:00
|
|
|
ClientThreadProxy(int func, const String& name, const String& item, bool start, const NamedList* params, Window* wnd, Window* skip);
|
2005-08-13 02:02:55 +00:00
|
|
|
void process();
|
|
|
|
bool execute();
|
|
|
|
private:
|
|
|
|
int m_func;
|
|
|
|
bool m_rval;
|
|
|
|
String m_name;
|
|
|
|
String m_text;
|
|
|
|
String m_item;
|
|
|
|
bool m_bool;
|
|
|
|
String* m_rtext;
|
|
|
|
bool* m_rbool;
|
|
|
|
Window* m_wnd;
|
|
|
|
Window* m_skip;
|
|
|
|
const NamedList* m_params;
|
|
|
|
};
|
|
|
|
|
2006-01-30 20:44:03 +00:00
|
|
|
|
2005-07-12 16:05:29 +00:00
|
|
|
// utility function to check if a string begins and ends with -dashes-
|
2006-04-08 18:03:28 +00:00
|
|
|
static bool checkDashes(const String& str)
|
|
|
|
{
|
|
|
|
return str.startsWith("-") && str.endsWith("-");
|
|
|
|
}
|
|
|
|
|
|
|
|
// utility function to make empty a string that begins and ends with -dashes-
|
|
|
|
// returns true if fixed string is empty
|
|
|
|
static bool fixDashes(String& str)
|
2005-07-12 16:05:29 +00:00
|
|
|
{
|
2006-04-08 18:03:28 +00:00
|
|
|
if (checkDashes(str))
|
2005-07-12 16:05:29 +00:00
|
|
|
str.clear();
|
2006-04-08 18:03:28 +00:00
|
|
|
str.trimBlanks();
|
2005-07-12 16:05:29 +00:00
|
|
|
return str.null();
|
|
|
|
}
|
2006-04-08 18:03:28 +00:00
|
|
|
|
2005-07-04 22:04:47 +00:00
|
|
|
Window::Window(const char* id)
|
2005-07-14 21:41:32 +00:00
|
|
|
: m_id(id), m_visible(false), m_master(false), m_popup(false)
|
2005-07-04 22:04:47 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Window::~Window()
|
|
|
|
{
|
|
|
|
if (Client::self())
|
|
|
|
Client::self()->m_windows.remove(this,false);
|
|
|
|
}
|
|
|
|
|
|
|
|
const String& Window::toString() const
|
|
|
|
{
|
|
|
|
return m_id;
|
|
|
|
}
|
|
|
|
|
2005-07-12 20:51:47 +00:00
|
|
|
void Window::title(const String& text)
|
|
|
|
{
|
|
|
|
m_title = text;
|
|
|
|
}
|
|
|
|
|
2005-07-04 22:04:47 +00:00
|
|
|
bool Window::related(const Window* wnd) const
|
|
|
|
{
|
|
|
|
if ((wnd == this) || !wnd || wnd->master())
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2005-07-25 22:44:34 +00:00
|
|
|
bool Window::setParams(const NamedList& params)
|
|
|
|
{
|
|
|
|
bool ok = true;
|
|
|
|
unsigned int l = params.length();
|
|
|
|
for (unsigned int i = 0; i < l; i++) {
|
|
|
|
const NamedString* s = params.getParam(i);
|
|
|
|
if (s) {
|
|
|
|
String n(s->name());
|
|
|
|
if (n == "title")
|
|
|
|
title(*s);
|
|
|
|
else if (n.startSkip("show:",false))
|
|
|
|
ok = setShow(n,s->toBoolean()) && ok;
|
|
|
|
else if (n.startSkip("active:",false))
|
|
|
|
ok = setActive(n,s->toBoolean()) && ok;
|
|
|
|
else if (n.startSkip("check:",false))
|
|
|
|
ok = setCheck(n,s->toBoolean()) && ok;
|
|
|
|
else if (n.startSkip("select:",false))
|
|
|
|
ok = setSelect(n,*s) && ok;
|
|
|
|
else if (n.find(':') < 0)
|
|
|
|
ok = setText(n,*s) && ok;
|
|
|
|
else
|
|
|
|
ok = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
2006-01-30 20:44:03 +00:00
|
|
|
bool Window::addTableRow(const String& name, const String& item, const NamedList* data, bool atStart)
|
|
|
|
{
|
|
|
|
DDebug(ClientDriver::self(),DebugInfo,"stub addTableRow('%s','%s',%p,%s) [%p]",
|
|
|
|
name.c_str(),item.c_str(),data,String::boolText(atStart),this);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Window::delTableRow(const String& name, const String& item)
|
|
|
|
{
|
|
|
|
DDebug(ClientDriver::self(),DebugInfo,"stub delTableRow('%s','%s') [%p]",
|
|
|
|
name.c_str(),item.c_str(),this);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Window::setTableRow(const String& name, const String& item, const NamedList* data)
|
|
|
|
{
|
|
|
|
DDebug(ClientDriver::self(),DebugInfo,"stub setTableRow('%s','%s',%p) [%p]",
|
|
|
|
name.c_str(),item.c_str(),data,this);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2006-04-08 18:03:28 +00:00
|
|
|
bool Window::getTableRow(const String& name, const String& item, NamedList* data)
|
|
|
|
{
|
|
|
|
DDebug(ClientDriver::self(),DebugInfo,"stub getTableRow('%s','%s',%p) [%p]",
|
|
|
|
name.c_str(),item.c_str(),data,this);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2006-01-30 20:44:03 +00:00
|
|
|
bool Window::clearTable(const String& name)
|
|
|
|
{
|
|
|
|
DDebug(ClientDriver::self(),DebugInfo,"stub clearTable('%s') [%p]",
|
|
|
|
name.c_str(),this);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2005-07-04 22:04:47 +00:00
|
|
|
|
|
|
|
UIFactory::UIFactory(const char* type, const char* name)
|
|
|
|
: String(name)
|
|
|
|
{
|
|
|
|
if (ClientDriver::self() && ClientDriver::self()->factory(this,type))
|
|
|
|
return;
|
|
|
|
Debug(ClientDriver::self(),DebugGoOn,"Could not register '%s' factory type '%s'",
|
|
|
|
name,type);
|
|
|
|
}
|
|
|
|
|
|
|
|
UIFactory::~UIFactory()
|
|
|
|
{
|
|
|
|
if (ClientDriver::self())
|
|
|
|
ClientDriver::self()->factory(this,0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-08-13 02:02:55 +00:00
|
|
|
static Mutex s_proxyMutex;
|
|
|
|
static ClientThreadProxy* s_proxy = 0;
|
|
|
|
static bool s_busy = false;
|
|
|
|
|
|
|
|
ClientThreadProxy::ClientThreadProxy(int func, const String& name, bool show, Window* wnd, Window* skip)
|
|
|
|
: m_func(func), m_rval(false),
|
|
|
|
m_name(name), m_bool(show), m_rtext(0), m_rbool(0),
|
|
|
|
m_wnd(wnd), m_skip(skip), m_params(0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
ClientThreadProxy::ClientThreadProxy(int func, const String& name, const String& text, Window* wnd, Window* skip)
|
|
|
|
: m_func(func), m_rval(false),
|
2005-08-18 22:46:35 +00:00
|
|
|
m_name(name), m_text(text), m_bool(false), m_rtext(0), m_rbool(0),
|
2005-08-13 02:02:55 +00:00
|
|
|
m_wnd(wnd), m_skip(skip), m_params(0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
ClientThreadProxy::ClientThreadProxy(int func, const String& name, const String& text, const String& item, bool show, Window* wnd, Window* skip)
|
|
|
|
: m_func(func), m_rval(false),
|
2005-08-18 22:46:35 +00:00
|
|
|
m_name(name), m_text(text), m_item(item), m_bool(show), m_rtext(0), m_rbool(0),
|
2005-08-13 02:02:55 +00:00
|
|
|
m_wnd(wnd), m_skip(skip), m_params(0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
ClientThreadProxy::ClientThreadProxy(int func, const String& name, String* rtext, bool* rbool, Window* wnd, Window* skip)
|
|
|
|
: m_func(func), m_rval(false),
|
2005-08-18 22:46:35 +00:00
|
|
|
m_name(name), m_bool(false), m_rtext(rtext), m_rbool(rbool),
|
2005-08-13 02:02:55 +00:00
|
|
|
m_wnd(wnd), m_skip(skip), m_params(0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
ClientThreadProxy::ClientThreadProxy(int func, const String& name, const NamedList* params, const Window* parent)
|
|
|
|
: m_func(func), m_rval(false),
|
2005-08-18 22:46:35 +00:00
|
|
|
m_name(name), m_bool(false), m_rtext(0), m_rbool(0),
|
2005-08-13 02:02:55 +00:00
|
|
|
m_wnd(const_cast<Window*>(parent)), m_skip(0), m_params(params)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2006-01-30 20:44:03 +00:00
|
|
|
ClientThreadProxy::ClientThreadProxy(int func, const String& name, const String& item, bool start, const NamedList* params, Window* wnd, Window* skip)
|
|
|
|
: m_func(func), m_rval(false),
|
|
|
|
m_name(name), m_item(item), m_bool(start), m_rtext(0), m_rbool(0),
|
|
|
|
m_wnd(wnd), m_skip(skip), m_params(params)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2005-08-13 02:02:55 +00:00
|
|
|
void ClientThreadProxy::process()
|
|
|
|
{
|
|
|
|
Debugger debug(DebugAll,"ClientThreadProxy::process()"," %d [%p]",m_func,this);
|
|
|
|
Client* client = Client::self();
|
|
|
|
if (!client) {
|
|
|
|
s_busy = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
switch (m_func) {
|
|
|
|
case setVisible:
|
|
|
|
m_rval = Client::setVisible(m_name,m_bool);
|
|
|
|
break;
|
|
|
|
case openPopup:
|
|
|
|
m_rval = Client::openPopup(m_name,m_params,m_wnd);
|
|
|
|
break;
|
|
|
|
case hasElement:
|
|
|
|
m_rval = client->hasElement(m_name,m_wnd,m_skip);
|
|
|
|
break;
|
|
|
|
case setShow:
|
|
|
|
m_rval = client->setShow(m_name,m_bool,m_wnd,m_skip);
|
|
|
|
break;
|
|
|
|
case setText:
|
|
|
|
m_rval = client->setText(m_name,m_text,m_wnd,m_skip);
|
|
|
|
break;
|
|
|
|
case setActive:
|
|
|
|
m_rval = client->setActive(m_name,m_bool,m_wnd,m_skip);
|
|
|
|
break;
|
|
|
|
case setCheck:
|
|
|
|
m_rval = client->setCheck(m_name,m_bool,m_wnd,m_skip);
|
|
|
|
break;
|
|
|
|
case setSelect:
|
|
|
|
m_rval = client->setSelect(m_name,m_text,m_wnd,m_skip);
|
|
|
|
break;
|
|
|
|
case setUrgent:
|
|
|
|
m_rval = client->setUrgent(m_name,m_bool,m_wnd,m_skip);
|
|
|
|
break;
|
2006-04-08 18:03:28 +00:00
|
|
|
case hasOption:
|
|
|
|
m_rval = client->hasOption(m_name,m_text,m_wnd,m_skip);
|
|
|
|
break;
|
2005-08-13 02:02:55 +00:00
|
|
|
case addOption:
|
|
|
|
m_rval = client->addOption(m_name,m_item,m_bool,m_text,m_wnd,m_skip);
|
|
|
|
break;
|
|
|
|
case delOption:
|
|
|
|
m_rval = client->delOption(m_name,m_text,m_wnd,m_skip);
|
|
|
|
break;
|
2006-01-30 20:44:03 +00:00
|
|
|
case addTableRow:
|
|
|
|
m_rval = client->addTableRow(m_name,m_item,m_params,m_bool,m_wnd,m_skip);
|
|
|
|
break;
|
|
|
|
case delTableRow:
|
|
|
|
m_rval = client->delTableRow(m_name,m_text,m_wnd,m_skip);
|
|
|
|
break;
|
|
|
|
case setTableRow:
|
|
|
|
m_rval = client->setTableRow(m_name,m_item,m_params,m_wnd,m_skip);
|
|
|
|
break;
|
2006-04-08 18:03:28 +00:00
|
|
|
case getTableRow:
|
|
|
|
m_rval = client->getTableRow(m_name,m_item,const_cast<NamedList*>(m_params),m_wnd,m_skip);
|
|
|
|
break;
|
|
|
|
case clearTable:
|
|
|
|
m_rval = client->clearTable(m_name);
|
|
|
|
break;
|
2005-08-13 02:02:55 +00:00
|
|
|
case getText:
|
|
|
|
m_rval = client->getText(m_name,*m_rtext,m_wnd,m_skip);
|
|
|
|
break;
|
|
|
|
case getCheck:
|
|
|
|
m_rval = client->getCheck(m_name,*m_rbool,m_wnd,m_skip);
|
|
|
|
break;
|
|
|
|
case getSelect:
|
|
|
|
m_rval = client->getSelect(m_name,*m_rtext,m_wnd,m_skip);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
s_busy = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ClientThreadProxy::execute()
|
|
|
|
{
|
2005-08-18 22:46:35 +00:00
|
|
|
Debugger debug(DebugAll,"ClientThreadProxy::execute()"," %d in %p [%p]",
|
|
|
|
m_func,Thread::current(),this);
|
2005-08-13 02:02:55 +00:00
|
|
|
s_proxyMutex.lock();
|
|
|
|
s_proxy = this;
|
2005-10-31 18:22:07 +00:00
|
|
|
s_busy = true;
|
2005-08-13 02:02:55 +00:00
|
|
|
while (s_busy)
|
|
|
|
Thread::yield();
|
|
|
|
s_proxyMutex.unlock();
|
|
|
|
return m_rval;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-04 22:04:47 +00:00
|
|
|
Client* Client::s_client = 0;
|
|
|
|
int Client::s_changing = 0;
|
|
|
|
|
|
|
|
Client::Client(const char *name)
|
2006-04-08 18:03:28 +00:00
|
|
|
: Thread(name), m_initialized(false), m_line(0), m_oneThread(true),
|
2005-07-27 18:31:47 +00:00
|
|
|
m_multiLines(false), m_autoAnswer(false)
|
2005-07-04 22:04:47 +00:00
|
|
|
{
|
|
|
|
s_client = this;
|
2006-01-30 20:44:03 +00:00
|
|
|
Engine::install(new UICdrHandler);
|
2006-04-08 18:03:28 +00:00
|
|
|
Engine::install(new UIUserHandler);
|
2005-07-04 22:04:47 +00:00
|
|
|
Engine::install(new UIHandler);
|
|
|
|
}
|
|
|
|
|
|
|
|
Client::~Client()
|
|
|
|
{
|
|
|
|
m_windows.clear();
|
|
|
|
s_client = 0;
|
|
|
|
Engine::halt(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Client::run()
|
|
|
|
{
|
|
|
|
loadWindows();
|
|
|
|
Message msg("ui.event");
|
|
|
|
msg.setParam("event","load");
|
|
|
|
Engine::dispatch(msg);
|
|
|
|
initWindows();
|
2005-07-27 18:31:47 +00:00
|
|
|
initClient();
|
2005-07-25 22:44:34 +00:00
|
|
|
updateFrom(0);
|
2005-07-04 22:04:47 +00:00
|
|
|
setStatus("");
|
2006-04-08 18:03:28 +00:00
|
|
|
m_initialized = true;
|
2005-07-04 22:04:47 +00:00
|
|
|
msg.setParam("event","init");
|
|
|
|
Engine::dispatch(msg);
|
|
|
|
main();
|
|
|
|
}
|
|
|
|
|
|
|
|
Window* Client::getWindow(const String& name)
|
|
|
|
{
|
|
|
|
if (!s_client)
|
|
|
|
return 0;
|
|
|
|
ObjList* l = s_client->m_windows.find(name);
|
|
|
|
return static_cast<Window*>(l ? l->get() : 0);
|
|
|
|
}
|
|
|
|
|
2005-07-12 20:51:47 +00:00
|
|
|
ObjList* Client::listWindows()
|
|
|
|
{
|
|
|
|
if (!s_client)
|
|
|
|
return 0;
|
|
|
|
ObjList* lst = 0;
|
|
|
|
for (ObjList* l = &s_client->m_windows; l; l = l->next()) {
|
|
|
|
Window* w = static_cast<Window*>(l->get());
|
|
|
|
if (w) {
|
|
|
|
if (!lst)
|
|
|
|
lst = new ObjList;
|
|
|
|
lst->append(new String(w->id()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return lst;
|
|
|
|
}
|
|
|
|
|
2005-07-04 22:04:47 +00:00
|
|
|
bool Client::setVisible(const String& name, bool show)
|
|
|
|
{
|
2005-08-13 02:02:55 +00:00
|
|
|
if (s_client && s_client->needProxy()) {
|
|
|
|
ClientThreadProxy proxy(ClientThreadProxy::setVisible,name,show);
|
|
|
|
return proxy.execute();
|
|
|
|
}
|
2005-07-04 22:04:47 +00:00
|
|
|
Window* w = getWindow(name);
|
|
|
|
if (!w)
|
|
|
|
return false;
|
|
|
|
w->visible(show);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Client::getVisible(const String& name)
|
|
|
|
{
|
|
|
|
Window* w = getWindow(name);
|
|
|
|
return w && w->visible();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Client::initWindows()
|
|
|
|
{
|
|
|
|
ObjList* l = &m_windows;
|
|
|
|
for (; l; l = l->next()) {
|
|
|
|
Window* w = static_cast<Window*>(l->get());
|
|
|
|
if (w)
|
|
|
|
w->init();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-07-27 18:31:47 +00:00
|
|
|
void Client::initClient()
|
|
|
|
{
|
2006-01-26 00:00:36 +00:00
|
|
|
bool tmp =
|
2005-07-27 18:31:47 +00:00
|
|
|
getWindow("channels") || hasElement("channels") ||
|
|
|
|
getWindow("lines") || hasElement("lines");
|
2006-01-26 00:00:36 +00:00
|
|
|
m_multiLines = Engine::config().getBoolValue("client","multilines",tmp);
|
|
|
|
tmp = false;
|
|
|
|
getCheck("autoanswer",tmp);
|
|
|
|
m_autoAnswer = Engine::config().getBoolValue("client","autoanswer",tmp);
|
2005-07-27 18:31:47 +00:00
|
|
|
setCheck("multilines",m_multiLines);
|
2006-01-26 00:00:36 +00:00
|
|
|
setCheck("autoanswer",m_autoAnswer);
|
2005-07-27 18:31:47 +00:00
|
|
|
}
|
|
|
|
|
2005-07-04 22:04:47 +00:00
|
|
|
void Client::moveRelated(const Window* wnd, int dx, int dy)
|
|
|
|
{
|
|
|
|
if (!wnd)
|
|
|
|
return;
|
|
|
|
ObjList* l = &m_windows;
|
|
|
|
for (; l; l = l->next()) {
|
|
|
|
Window* w = static_cast<Window*>(l->get());
|
|
|
|
if (w && (w != wnd) && wnd->related(w))
|
|
|
|
w->moveRel(dx,dy);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-07-27 18:31:47 +00:00
|
|
|
bool Client::openPopup(const String& name, const NamedList* params, const Window* parent)
|
2005-07-25 22:44:34 +00:00
|
|
|
{
|
2005-08-13 02:02:55 +00:00
|
|
|
if (s_client && s_client->needProxy()) {
|
|
|
|
ClientThreadProxy proxy(ClientThreadProxy::openPopup,name,params,parent);
|
|
|
|
return proxy.execute();
|
|
|
|
}
|
2005-07-25 22:44:34 +00:00
|
|
|
Window* wnd = getWindow(name);
|
|
|
|
if (!wnd)
|
|
|
|
return false;
|
|
|
|
if (params)
|
|
|
|
wnd->setParams(*params);
|
2005-07-27 18:31:47 +00:00
|
|
|
if (parent)
|
|
|
|
wnd->setOver(parent);
|
2005-07-25 22:44:34 +00:00
|
|
|
wnd->show();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2006-01-26 00:00:36 +00:00
|
|
|
bool Client::openMessage(const char* text, const Window* parent)
|
|
|
|
{
|
|
|
|
NamedList params("");
|
|
|
|
params.addParam("text",text);
|
2006-04-08 18:03:28 +00:00
|
|
|
params.addParam("modal",String::boolText(parent != 0));
|
2006-01-26 00:00:36 +00:00
|
|
|
return openPopup("message",¶ms,parent);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Client::openConfirm(const char* text, const Window* parent)
|
|
|
|
{
|
|
|
|
NamedList params("");
|
|
|
|
params.addParam("text",text);
|
2006-04-08 18:03:28 +00:00
|
|
|
params.addParam("modal",String::boolText(parent != 0));
|
2006-01-26 00:00:36 +00:00
|
|
|
return openPopup("confirm",¶ms,parent);
|
|
|
|
}
|
|
|
|
|
2005-07-27 18:31:47 +00:00
|
|
|
bool Client::hasElement(const String& name, Window* wnd, Window* skip)
|
|
|
|
{
|
2005-08-13 02:02:55 +00:00
|
|
|
if (needProxy()) {
|
|
|
|
ClientThreadProxy proxy(ClientThreadProxy::hasElement,name,false,wnd,skip);
|
|
|
|
return proxy.execute();
|
|
|
|
}
|
2005-07-27 18:31:47 +00:00
|
|
|
if (wnd)
|
|
|
|
return wnd->hasElement(name);
|
|
|
|
ObjList* l = &m_windows;
|
|
|
|
for (; l; l = l->next()) {
|
|
|
|
wnd = static_cast<Window*>(l->get());
|
|
|
|
if (wnd && (wnd != skip) && wnd->hasElement(name))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2005-07-04 22:04:47 +00:00
|
|
|
bool Client::setShow(const String& name, bool visible, Window* wnd, Window* skip)
|
|
|
|
{
|
2005-08-13 02:02:55 +00:00
|
|
|
if (needProxy()) {
|
|
|
|
ClientThreadProxy proxy(ClientThreadProxy::setShow,name,visible,wnd,skip);
|
|
|
|
return proxy.execute();
|
|
|
|
}
|
2005-07-04 22:04:47 +00:00
|
|
|
if (wnd)
|
|
|
|
return wnd->setShow(name,visible);
|
|
|
|
++s_changing;
|
|
|
|
bool ok = false;
|
|
|
|
ObjList* l = &m_windows;
|
|
|
|
for (; l; l = l->next()) {
|
|
|
|
wnd = static_cast<Window*>(l->get());
|
|
|
|
if (wnd && (wnd != skip))
|
|
|
|
ok = wnd->setShow(name,visible) || ok;
|
|
|
|
}
|
|
|
|
--s_changing;
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Client::setActive(const String& name, bool active, Window* wnd, Window* skip)
|
|
|
|
{
|
2005-08-13 02:02:55 +00:00
|
|
|
if (needProxy()) {
|
|
|
|
ClientThreadProxy proxy(ClientThreadProxy::setActive,name,active,wnd,skip);
|
|
|
|
return proxy.execute();
|
|
|
|
}
|
2005-07-04 22:04:47 +00:00
|
|
|
if (wnd)
|
|
|
|
return wnd->setActive(name,active);
|
|
|
|
++s_changing;
|
|
|
|
bool ok = false;
|
|
|
|
ObjList* l = &m_windows;
|
|
|
|
for (; l; l = l->next()) {
|
|
|
|
wnd = static_cast<Window*>(l->get());
|
|
|
|
if (wnd && (wnd != skip))
|
|
|
|
ok = wnd->setActive(name,active) || ok;
|
|
|
|
}
|
|
|
|
--s_changing;
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Client::setText(const String& name, const String& text, Window* wnd, Window* skip)
|
|
|
|
{
|
2005-08-13 02:02:55 +00:00
|
|
|
if (needProxy()) {
|
|
|
|
ClientThreadProxy proxy(ClientThreadProxy::setText,name,text,wnd,skip);
|
|
|
|
return proxy.execute();
|
|
|
|
}
|
2005-07-04 22:04:47 +00:00
|
|
|
if (wnd)
|
|
|
|
return wnd->setText(name,text);
|
|
|
|
++s_changing;
|
|
|
|
bool ok = false;
|
|
|
|
ObjList* l = &m_windows;
|
|
|
|
for (; l; l = l->next()) {
|
|
|
|
wnd = static_cast<Window*>(l->get());
|
|
|
|
if (wnd && (wnd != skip))
|
|
|
|
ok = wnd->setText(name,text) || ok;
|
|
|
|
}
|
|
|
|
--s_changing;
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Client::setCheck(const String& name, bool checked, Window* wnd, Window* skip)
|
|
|
|
{
|
2005-08-13 02:02:55 +00:00
|
|
|
if (needProxy()) {
|
|
|
|
ClientThreadProxy proxy(ClientThreadProxy::setCheck,name,checked,wnd,skip);
|
|
|
|
return proxy.execute();
|
|
|
|
}
|
2005-07-04 22:04:47 +00:00
|
|
|
if (wnd)
|
|
|
|
return wnd->setCheck(name,checked);
|
|
|
|
++s_changing;
|
|
|
|
bool ok = false;
|
|
|
|
ObjList* l = &m_windows;
|
|
|
|
for (; l; l = l->next()) {
|
|
|
|
wnd = static_cast<Window*>(l->get());
|
|
|
|
if (wnd && (wnd != skip))
|
|
|
|
ok = wnd->setCheck(name,checked) || ok;
|
|
|
|
}
|
|
|
|
--s_changing;
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Client::setSelect(const String& name, const String& item, Window* wnd, Window* skip)
|
|
|
|
{
|
2005-08-13 02:02:55 +00:00
|
|
|
if (needProxy()) {
|
|
|
|
ClientThreadProxy proxy(ClientThreadProxy::setSelect,name,item,wnd,skip);
|
|
|
|
return proxy.execute();
|
|
|
|
}
|
2005-07-04 22:04:47 +00:00
|
|
|
if (wnd)
|
|
|
|
return wnd->setSelect(name,item);
|
|
|
|
++s_changing;
|
|
|
|
bool ok = false;
|
|
|
|
ObjList* l = &m_windows;
|
|
|
|
for (; l; l = l->next()) {
|
|
|
|
wnd = static_cast<Window*>(l->get());
|
|
|
|
if (wnd && (wnd != skip))
|
|
|
|
ok = wnd->setSelect(name,item) || ok;
|
|
|
|
}
|
|
|
|
--s_changing;
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
2005-07-27 18:31:47 +00:00
|
|
|
bool Client::setUrgent(const String& name, bool urgent, Window* wnd, Window* skip)
|
|
|
|
{
|
2005-08-13 02:02:55 +00:00
|
|
|
if (needProxy()) {
|
|
|
|
ClientThreadProxy proxy(ClientThreadProxy::setUrgent,name,urgent,wnd,skip);
|
|
|
|
return proxy.execute();
|
|
|
|
}
|
2005-07-27 18:31:47 +00:00
|
|
|
if (wnd)
|
|
|
|
return wnd->setUrgent(name,urgent);
|
|
|
|
++s_changing;
|
|
|
|
bool ok = false;
|
|
|
|
ObjList* l = &m_windows;
|
|
|
|
for (; l; l = l->next()) {
|
|
|
|
wnd = static_cast<Window*>(l->get());
|
|
|
|
if (wnd && (wnd != skip))
|
|
|
|
ok = wnd->setUrgent(name,urgent) || ok;
|
|
|
|
}
|
|
|
|
--s_changing;
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
2006-04-08 18:03:28 +00:00
|
|
|
bool Client::hasOption(const String& name, const String& item, Window* wnd, Window* skip)
|
|
|
|
{
|
|
|
|
if (needProxy()) {
|
|
|
|
ClientThreadProxy proxy(ClientThreadProxy::hasOption,name,item,wnd,skip);
|
|
|
|
return proxy.execute();
|
|
|
|
}
|
|
|
|
if (wnd)
|
|
|
|
return wnd->hasOption(name,item);
|
|
|
|
ObjList* l = &m_windows;
|
|
|
|
for (; l; l = l->next()) {
|
|
|
|
wnd = static_cast<Window*>(l->get());
|
|
|
|
if (wnd && (wnd != skip) && wnd->hasOption(name,item))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2005-07-25 22:44:34 +00:00
|
|
|
bool Client::addOption(const String& name, const String& item, bool atStart, const String& text, Window* wnd, Window* skip)
|
2005-07-04 22:04:47 +00:00
|
|
|
{
|
2005-08-13 02:02:55 +00:00
|
|
|
if (needProxy()) {
|
|
|
|
ClientThreadProxy proxy(ClientThreadProxy::addOption,name,text,item,atStart,wnd,skip);
|
|
|
|
return proxy.execute();
|
|
|
|
}
|
2005-07-04 22:04:47 +00:00
|
|
|
if (wnd)
|
2005-07-25 22:44:34 +00:00
|
|
|
return wnd->addOption(name,item,atStart,text);
|
2005-07-04 22:04:47 +00:00
|
|
|
++s_changing;
|
|
|
|
bool ok = false;
|
|
|
|
ObjList* l = &m_windows;
|
|
|
|
for (; l; l = l->next()) {
|
|
|
|
wnd = static_cast<Window*>(l->get());
|
|
|
|
if (wnd && (wnd != skip))
|
2005-07-25 22:44:34 +00:00
|
|
|
ok = wnd->addOption(name,item,atStart,text) || ok;
|
2005-07-04 22:04:47 +00:00
|
|
|
}
|
|
|
|
--s_changing;
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Client::delOption(const String& name, const String& item, Window* wnd, Window* skip)
|
|
|
|
{
|
2005-08-13 02:02:55 +00:00
|
|
|
if (needProxy()) {
|
|
|
|
ClientThreadProxy proxy(ClientThreadProxy::delOption,name,item,wnd,skip);
|
|
|
|
return proxy.execute();
|
|
|
|
}
|
2005-07-04 22:04:47 +00:00
|
|
|
if (wnd)
|
|
|
|
return wnd->delOption(name,item);
|
|
|
|
++s_changing;
|
|
|
|
bool ok = false;
|
|
|
|
ObjList* l = &m_windows;
|
|
|
|
for (; l; l = l->next()) {
|
|
|
|
wnd = static_cast<Window*>(l->get());
|
|
|
|
if (wnd && (wnd != skip))
|
|
|
|
ok = wnd->delOption(name,item) || ok;
|
|
|
|
}
|
|
|
|
--s_changing;
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
2006-01-30 20:44:03 +00:00
|
|
|
bool Client::addTableRow(const String& name, const String& item, const NamedList* data, bool atStart, Window* wnd, Window* skip)
|
|
|
|
{
|
|
|
|
if (needProxy()) {
|
|
|
|
ClientThreadProxy proxy(ClientThreadProxy::addTableRow,name,item,atStart,data,wnd,skip);
|
|
|
|
return proxy.execute();
|
|
|
|
}
|
|
|
|
if (wnd)
|
|
|
|
return wnd->addTableRow(name,item,data,atStart);
|
|
|
|
++s_changing;
|
|
|
|
bool ok = false;
|
|
|
|
ObjList* l = &m_windows;
|
|
|
|
for (; l; l = l->next()) {
|
|
|
|
wnd = static_cast<Window*>(l->get());
|
|
|
|
if (wnd && (wnd != skip))
|
|
|
|
ok = wnd->addTableRow(name,item,data,atStart) || ok;
|
|
|
|
}
|
|
|
|
--s_changing;
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Client::delTableRow(const String& name, const String& item, Window* wnd, Window* skip)
|
|
|
|
{
|
|
|
|
if (needProxy()) {
|
|
|
|
ClientThreadProxy proxy(ClientThreadProxy::delTableRow,name,item,wnd,skip);
|
|
|
|
return proxy.execute();
|
|
|
|
}
|
|
|
|
if (wnd)
|
|
|
|
return wnd->delTableRow(name,item);
|
|
|
|
++s_changing;
|
|
|
|
bool ok = false;
|
|
|
|
ObjList* l = &m_windows;
|
|
|
|
for (; l; l = l->next()) {
|
|
|
|
wnd = static_cast<Window*>(l->get());
|
|
|
|
if (wnd && (wnd != skip))
|
|
|
|
ok = wnd->delTableRow(name,item) || ok;
|
|
|
|
}
|
|
|
|
--s_changing;
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Client::setTableRow(const String& name, const String& item, const NamedList* data, Window* wnd, Window* skip)
|
|
|
|
{
|
|
|
|
if (needProxy()) {
|
|
|
|
ClientThreadProxy proxy(ClientThreadProxy::setTableRow,name,item,false,data,wnd,skip);
|
|
|
|
return proxy.execute();
|
|
|
|
}
|
|
|
|
if (wnd)
|
|
|
|
return wnd->setTableRow(name,item,data);
|
|
|
|
++s_changing;
|
|
|
|
bool ok = false;
|
|
|
|
ObjList* l = &m_windows;
|
|
|
|
for (; l; l = l->next()) {
|
|
|
|
wnd = static_cast<Window*>(l->get());
|
|
|
|
if (wnd && (wnd != skip))
|
|
|
|
ok = wnd->setTableRow(name,item,data) || ok;
|
|
|
|
}
|
|
|
|
--s_changing;
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
2006-04-08 18:03:28 +00:00
|
|
|
bool Client::getTableRow(const String& name, const String& item, NamedList* data, Window* wnd, Window* skip)
|
|
|
|
{
|
|
|
|
if (needProxy()) {
|
|
|
|
ClientThreadProxy proxy(ClientThreadProxy::getTableRow,name,item,false,data,wnd,skip);
|
|
|
|
return proxy.execute();
|
|
|
|
}
|
|
|
|
if (wnd)
|
|
|
|
return wnd->getTableRow(name,item,data);
|
|
|
|
ObjList* l = &m_windows;
|
|
|
|
for (; l; l = l->next()) {
|
|
|
|
wnd = static_cast<Window*>(l->get());
|
|
|
|
if (wnd && (wnd != skip) && wnd->getTableRow(name,item,data))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Client::clearTable(const String& name, Window* wnd, Window* skip)
|
|
|
|
{
|
|
|
|
if (needProxy()) {
|
|
|
|
ClientThreadProxy proxy(ClientThreadProxy::clearTable,name,false,wnd,skip);
|
|
|
|
return proxy.execute();
|
|
|
|
}
|
|
|
|
if (wnd)
|
|
|
|
return wnd->clearTable(name);
|
|
|
|
++s_changing;
|
|
|
|
bool ok = false;
|
|
|
|
ObjList* l = &m_windows;
|
|
|
|
for (; l; l = l->next()) {
|
|
|
|
wnd = static_cast<Window*>(l->get());
|
|
|
|
if (wnd && (wnd != skip))
|
|
|
|
ok = wnd->clearTable(name) || ok;
|
|
|
|
}
|
|
|
|
--s_changing;
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
2005-07-04 22:04:47 +00:00
|
|
|
bool Client::getText(const String& name, String& text, Window* wnd, Window* skip)
|
|
|
|
{
|
2005-08-13 02:02:55 +00:00
|
|
|
if (needProxy()) {
|
|
|
|
ClientThreadProxy proxy(ClientThreadProxy::getText,name,&text,0,wnd,skip);
|
|
|
|
return proxy.execute();
|
|
|
|
}
|
2005-07-04 22:04:47 +00:00
|
|
|
if (wnd)
|
|
|
|
return wnd->getText(name,text);
|
|
|
|
ObjList* l = &m_windows;
|
|
|
|
for (; l; l = l->next()) {
|
|
|
|
wnd = static_cast<Window*>(l->get());
|
|
|
|
if (wnd && (wnd != skip) && wnd->getText(name,text))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Client::getCheck(const String& name, bool& checked, Window* wnd, Window* skip)
|
|
|
|
{
|
2005-08-13 02:02:55 +00:00
|
|
|
if (needProxy()) {
|
|
|
|
ClientThreadProxy proxy(ClientThreadProxy::getCheck,name,0,&checked,wnd,skip);
|
|
|
|
return proxy.execute();
|
|
|
|
}
|
2005-07-04 22:04:47 +00:00
|
|
|
if (wnd)
|
|
|
|
return wnd->getCheck(name,checked);
|
|
|
|
ObjList* l = &m_windows;
|
|
|
|
for (; l; l = l->next()) {
|
|
|
|
wnd = static_cast<Window*>(l->get());
|
|
|
|
if (wnd && (wnd != skip) && wnd->getCheck(name,checked))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Client::getSelect(const String& name, String& item, Window* wnd, Window* skip)
|
|
|
|
{
|
2005-08-13 02:02:55 +00:00
|
|
|
if (needProxy()) {
|
|
|
|
ClientThreadProxy proxy(ClientThreadProxy::getSelect,name,&item,0,wnd,skip);
|
|
|
|
return proxy.execute();
|
|
|
|
}
|
2005-07-25 22:44:34 +00:00
|
|
|
if (wnd)
|
|
|
|
return wnd->getSelect(name,item);
|
|
|
|
ObjList* l = &m_windows;
|
|
|
|
for (; l; l = l->next()) {
|
|
|
|
wnd = static_cast<Window*>(l->get());
|
|
|
|
if (wnd && (wnd != skip) && wnd->getSelect(name,item))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2005-07-04 22:04:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Client::setStatus(const String& text, Window* wnd)
|
|
|
|
{
|
|
|
|
Debug(ClientDriver::self(),DebugInfo,"Status '%s' in window %p",text.c_str(),wnd);
|
|
|
|
return setText("status",text,wnd);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Client::setStatusLocked(const String& text, Window* wnd)
|
|
|
|
{
|
2005-08-13 02:02:55 +00:00
|
|
|
lockOther();
|
2005-07-04 22:04:47 +00:00
|
|
|
bool ok = setStatus(text,wnd);
|
2005-08-13 02:02:55 +00:00
|
|
|
unlockOther();
|
2005-07-04 22:04:47 +00:00
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Client::action(Window* wnd, const String& name)
|
|
|
|
{
|
|
|
|
DDebug(ClientDriver::self(),DebugInfo,"Action '%s' in %p",name.c_str(),wnd);
|
|
|
|
if (name == "call" || name == "callto") {
|
|
|
|
String target;
|
|
|
|
getText("callto",target,wnd);
|
2005-07-05 21:04:59 +00:00
|
|
|
target.trimBlanks();
|
|
|
|
if (target.null())
|
|
|
|
return false;
|
2005-07-04 22:04:47 +00:00
|
|
|
String line;
|
|
|
|
getText("line",line,wnd);
|
2005-07-05 21:04:59 +00:00
|
|
|
line.trimBlanks();
|
2006-04-08 18:03:28 +00:00
|
|
|
fixDashes(line);
|
2005-07-04 22:04:47 +00:00
|
|
|
String proto;
|
2005-07-05 21:04:59 +00:00
|
|
|
getText("protocol",proto,wnd);
|
|
|
|
proto.trimBlanks();
|
2006-04-08 18:03:28 +00:00
|
|
|
fixDashes(proto);
|
2005-07-05 21:04:59 +00:00
|
|
|
String account;
|
|
|
|
getText("account",account,wnd);
|
|
|
|
account.trimBlanks();
|
2006-04-08 18:03:28 +00:00
|
|
|
fixDashes(account);
|
2005-07-05 21:04:59 +00:00
|
|
|
return callStart(target,line,proto,account);
|
2005-07-04 22:04:47 +00:00
|
|
|
}
|
|
|
|
else if (name.startsWith("callto:"))
|
|
|
|
return callStart(name.substr(7));
|
|
|
|
else if (name == "accept") {
|
2005-07-27 18:31:47 +00:00
|
|
|
callAccept(m_activeId);
|
2005-07-04 22:04:47 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if (name.startsWith("accept:")) {
|
|
|
|
callAccept(name.substr(7));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if (name == "reject") {
|
2005-07-27 18:31:47 +00:00
|
|
|
callReject(m_activeId);
|
2005-07-04 22:04:47 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if (name.startsWith("reject:")) {
|
|
|
|
callReject(name.substr(7));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if (name == "hangup") {
|
2005-07-27 18:31:47 +00:00
|
|
|
callHangup(m_activeId);
|
2005-07-04 22:04:47 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if (name.startsWith("hangup:")) {
|
|
|
|
callHangup(name.substr(7));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if (name.startsWith("digit:")) {
|
|
|
|
emitDigit(name.at(6));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if (name.startsWith("line:")) {
|
|
|
|
int l = name.substr(5).toInteger(-1);
|
|
|
|
if (l >= 0) {
|
|
|
|
line(l);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2006-04-08 18:03:28 +00:00
|
|
|
// accounts window actions
|
|
|
|
else if (name == "acc_new") {
|
|
|
|
NamedList params("");
|
|
|
|
params.setParam("select:acc_provider","--");
|
|
|
|
params.setParam("acc_account","");
|
|
|
|
params.setParam("acc_account_orig","");
|
|
|
|
params.setParam("acc_username","");
|
|
|
|
params.setParam("acc_password","");
|
|
|
|
params.setParam("acc_server","");
|
|
|
|
params.setParam("acc_domain","");
|
|
|
|
params.setParam("acc_outbound","");
|
|
|
|
params.setParam("modal",String::boolText(true));
|
|
|
|
if (openPopup("account",¶ms,wnd))
|
|
|
|
return true;
|
|
|
|
}
|
2006-04-14 22:50:45 +00:00
|
|
|
else if ((name == "acc_edit") || (name == "accounts")) {
|
2006-04-08 18:03:28 +00:00
|
|
|
String acc;
|
|
|
|
if (getSelect("accounts",acc,wnd)) {
|
|
|
|
NamedList params("");
|
|
|
|
params.setParam("select:acc_provider","--");
|
|
|
|
params.setParam("acc_account",acc);
|
|
|
|
params.setParam("acc_account_orig",acc);
|
|
|
|
params.setParam("modal",String::boolText(true));
|
|
|
|
if (openPopup("account",¶ms,wnd))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else if (name == "acc_del") {
|
|
|
|
String acc;
|
|
|
|
if (getSelect("accounts",acc,wnd)) {
|
|
|
|
if (openConfirm("Delete account "+acc,wnd))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
2006-04-14 22:50:45 +00:00
|
|
|
else if (name == "acc_accept") {
|
|
|
|
}
|
2006-04-08 18:03:28 +00:00
|
|
|
// address book window actions
|
2006-04-14 22:50:45 +00:00
|
|
|
else if ((name == "abk_call") || (name == "contacts")) {
|
|
|
|
}
|
2006-04-08 18:03:28 +00:00
|
|
|
else if (name == "abk_new") {
|
|
|
|
NamedList params("");
|
|
|
|
params.setParam("abk_contact","");
|
|
|
|
params.setParam("abk_contact_orig","");
|
|
|
|
params.setParam("abk_number","");
|
|
|
|
params.setParam("modal",String::boolText(true));
|
|
|
|
if (openPopup("addrbook",¶ms,wnd))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if (name == "abk_edit") {
|
|
|
|
String cnt;
|
|
|
|
if (getSelect("contacts",cnt,wnd)) {
|
|
|
|
NamedList params("");
|
|
|
|
params.setParam("abk_contact_orig",cnt);
|
|
|
|
params.setParam("abk_contact",cnt);
|
|
|
|
params.setParam("modal",String::boolText(true));
|
|
|
|
if (openPopup("addrbook",¶ms,wnd))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else if (name == "abk_del") {
|
|
|
|
String cnt;
|
|
|
|
if (getSelect("contacts",cnt,wnd)) {
|
|
|
|
if (openConfirm("Delete contact "+cnt,wnd))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
2006-04-14 22:50:45 +00:00
|
|
|
else if (name == "abk_accept") {
|
|
|
|
}
|
2006-04-08 18:03:28 +00:00
|
|
|
// outgoing (placed) call log actions
|
|
|
|
else if (name == "log_out_clear") {
|
|
|
|
if (clearTable("log_outgoing"))
|
|
|
|
return true;
|
|
|
|
}
|
2006-04-14 22:50:45 +00:00
|
|
|
else if ((name == "log_out_call") || (name == "log_outgoing")) {
|
2006-04-08 18:03:28 +00:00
|
|
|
NamedList log("");
|
|
|
|
if (getTableRow("log_outgoing","",&log,wnd)) {
|
2006-04-14 22:50:45 +00:00
|
|
|
String* called = log.getParam("called");
|
|
|
|
if (called && *called && openConfirm("Call to "+*called,wnd))
|
|
|
|
return true;
|
2006-04-08 18:03:28 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
// incoming (received) call log actions
|
|
|
|
else if (name == "log_in_clear") {
|
|
|
|
if (clearTable("log_incoming"))
|
|
|
|
return true;
|
|
|
|
}
|
2006-04-14 22:50:45 +00:00
|
|
|
else if ((name == "log_in_call") || (name == "log_incoming")) {
|
|
|
|
NamedList log("");
|
|
|
|
if (getTableRow("log_incoming","",&log,wnd)) {
|
|
|
|
String* caller = log.getParam("caller");
|
|
|
|
if (caller && *caller && openConfirm("Call to "+*caller,wnd))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
// mixed call log actions
|
|
|
|
else if (name == "log_clear") {
|
|
|
|
if (clearTable("log_global"))
|
|
|
|
return true;
|
|
|
|
}
|
2006-04-08 18:03:28 +00:00
|
|
|
|
|
|
|
// unknown/unhandled - generate a message for them
|
2005-07-04 22:04:47 +00:00
|
|
|
Message* m = new Message("ui.event");
|
2005-07-12 20:51:47 +00:00
|
|
|
if (wnd)
|
|
|
|
m->addParam("window",wnd->id());
|
2005-07-04 22:04:47 +00:00
|
|
|
m->addParam("event","action");
|
|
|
|
m->addParam("name",name);
|
|
|
|
Engine::enqueue(m);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Client::toggle(Window* wnd, const String& name, bool active)
|
|
|
|
{
|
|
|
|
DDebug(ClientDriver::self(),DebugInfo,"Toggle '%s' %s in %p",
|
|
|
|
name.c_str(),String::boolText(active),wnd);
|
2006-04-08 18:03:28 +00:00
|
|
|
// handle the window visibility buttons, these will sync toggles themselves
|
2005-07-04 22:04:47 +00:00
|
|
|
if (setVisible(name,active))
|
|
|
|
return true;
|
2006-04-08 18:03:28 +00:00
|
|
|
// keep the toggle in sync in all windows
|
2005-07-04 22:04:47 +00:00
|
|
|
setCheck(name,active,0,wnd);
|
2005-07-27 18:31:47 +00:00
|
|
|
if (name == "autoanswer") {
|
|
|
|
m_autoAnswer = active;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (name == "multilines") {
|
|
|
|
m_multiLines = active;
|
|
|
|
return true;
|
|
|
|
}
|
2006-04-08 18:03:28 +00:00
|
|
|
|
|
|
|
// unknown/unhandled - generate a message for them
|
2005-07-04 22:04:47 +00:00
|
|
|
Message* m = new Message("ui.event");
|
2005-07-12 20:51:47 +00:00
|
|
|
if (wnd)
|
|
|
|
m->addParam("window",wnd->id());
|
2005-07-04 22:04:47 +00:00
|
|
|
m->addParam("event","toggle");
|
|
|
|
m->addParam("name",name);
|
|
|
|
m->addParam("active",String::boolText(active));
|
|
|
|
Engine::enqueue(m);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2005-07-25 22:44:34 +00:00
|
|
|
bool Client::select(Window* wnd, const String& name, const String& item, const String& text)
|
2005-07-04 22:04:47 +00:00
|
|
|
{
|
|
|
|
DDebug(ClientDriver::self(),DebugInfo,"Select '%s' '%s' in %p",
|
|
|
|
name.c_str(),item.c_str(),wnd);
|
2006-04-08 18:03:28 +00:00
|
|
|
// keep the item in sync in all windows
|
2005-07-04 22:04:47 +00:00
|
|
|
setSelect(name,item,0,wnd);
|
2005-07-25 22:44:34 +00:00
|
|
|
if (name == "channels") {
|
2005-07-27 18:31:47 +00:00
|
|
|
updateFrom(item);
|
2005-07-25 22:44:34 +00:00
|
|
|
return true;
|
|
|
|
}
|
2006-04-08 18:03:28 +00:00
|
|
|
else if (name == "account") {
|
2006-04-14 22:50:45 +00:00
|
|
|
if (checkDashes(item))
|
|
|
|
return true;
|
2006-04-08 18:03:28 +00:00
|
|
|
// selecting an account unselects protocol
|
2006-04-14 22:50:45 +00:00
|
|
|
if (setSelect("protocol","") || setSelect("protocol","--"))
|
|
|
|
return true;
|
2006-04-08 18:03:28 +00:00
|
|
|
}
|
|
|
|
else if (name == "protocol") {
|
2006-04-14 22:50:45 +00:00
|
|
|
if (checkDashes(item))
|
|
|
|
return true;
|
2006-04-08 18:03:28 +00:00
|
|
|
// selecting a protocol unselects account
|
2006-04-14 22:50:45 +00:00
|
|
|
if (setSelect("account","") || setSelect("account","--"))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if (name == "acc_provider") {
|
|
|
|
// apply provider template
|
|
|
|
if (checkDashes(item))
|
|
|
|
return true;
|
|
|
|
// reset selection after we apply it
|
|
|
|
if (setSelect(name,"--") || setSelect(name,"--"))
|
|
|
|
return true;
|
2006-04-08 18:03:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// unknown/unhandled - generate a message for them
|
2005-07-04 22:04:47 +00:00
|
|
|
Message* m = new Message("ui.event");
|
2005-07-12 20:51:47 +00:00
|
|
|
if (wnd)
|
|
|
|
m->addParam("window",wnd->id());
|
2005-07-04 22:04:47 +00:00
|
|
|
m->addParam("event","select");
|
|
|
|
m->addParam("name",name);
|
|
|
|
m->addParam("item",item);
|
2005-07-25 22:44:34 +00:00
|
|
|
if (text)
|
|
|
|
m->addParam("text",text);
|
2005-07-04 22:04:47 +00:00
|
|
|
Engine::enqueue(m);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Client::line(int newLine)
|
|
|
|
{
|
|
|
|
Debug(ClientDriver::self(),DebugInfo,"line(%d)",newLine);
|
|
|
|
m_line = newLine;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Client::callAccept(const char* callId)
|
|
|
|
{
|
|
|
|
Debug(ClientDriver::self(),DebugInfo,"callAccept('%s')",callId);
|
2005-08-19 23:21:31 +00:00
|
|
|
if (!driverLockLoop())
|
|
|
|
return;
|
2005-07-04 22:04:47 +00:00
|
|
|
ClientChannel* cc = static_cast<ClientChannel*>(ClientDriver::self()->find(callId));
|
|
|
|
if (cc) {
|
2005-07-25 22:44:34 +00:00
|
|
|
cc->ref();
|
|
|
|
cc->callAnswer();
|
|
|
|
setChannelInternal(cc);
|
|
|
|
cc->deref();
|
2005-07-04 22:04:47 +00:00
|
|
|
}
|
2005-08-19 23:21:31 +00:00
|
|
|
driverUnlock();
|
2005-07-04 22:04:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Client::callReject(const char* callId)
|
|
|
|
{
|
|
|
|
Debug(ClientDriver::self(),DebugInfo,"callReject('%s')",callId);
|
|
|
|
if (!ClientDriver::self())
|
|
|
|
return;
|
|
|
|
Message* m = new Message("call.drop");
|
|
|
|
m->addParam("id",callId ? callId : ClientDriver::self()->name().c_str());
|
|
|
|
m->addParam("error","rejected");
|
|
|
|
m->addParam("reason","Refused");
|
|
|
|
Engine::enqueue(m);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Client::callHangup(const char* callId)
|
|
|
|
{
|
|
|
|
Debug(ClientDriver::self(),DebugInfo,"callHangup('%s')",callId);
|
|
|
|
if (!ClientDriver::self())
|
|
|
|
return;
|
|
|
|
Message* m = new Message("call.drop");
|
|
|
|
m->addParam("id",callId ? callId : ClientDriver::self()->name().c_str());
|
|
|
|
m->addParam("reason","User hangup");
|
|
|
|
Engine::enqueue(m);
|
|
|
|
}
|
|
|
|
|
2005-07-05 21:04:59 +00:00
|
|
|
bool Client::callStart(const String& target, const String& line,
|
|
|
|
const String& proto, const String& account)
|
2005-07-04 22:04:47 +00:00
|
|
|
{
|
2005-07-05 21:04:59 +00:00
|
|
|
Debug(ClientDriver::self(),DebugInfo,"callStart('%s','%s','%s','%s')",
|
|
|
|
target.c_str(),line.c_str(),proto.c_str(),account.c_str());
|
2005-07-04 22:04:47 +00:00
|
|
|
if (target.null())
|
|
|
|
return false;
|
2005-08-19 23:21:31 +00:00
|
|
|
if (!driverLockLoop())
|
|
|
|
return false;
|
2005-07-27 18:31:47 +00:00
|
|
|
ClientChannel* cc = new ClientChannel(target);
|
2005-07-04 22:04:47 +00:00
|
|
|
Message* m = cc->message("call.route");
|
2005-08-19 23:21:31 +00:00
|
|
|
driverUnlock();
|
2005-07-08 15:34:15 +00:00
|
|
|
Regexp r("^[a-z0-9]\\+/");
|
2005-07-12 16:05:29 +00:00
|
|
|
bool hasProto = r.matches(target.safe());
|
|
|
|
if (hasProto)
|
2005-07-04 22:04:47 +00:00
|
|
|
m->setParam("callto",target);
|
2005-07-12 16:05:29 +00:00
|
|
|
else if (proto)
|
|
|
|
m->setParam("callto",proto + "/" + target);
|
2005-07-04 22:04:47 +00:00
|
|
|
else
|
|
|
|
m->setParam("called",target);
|
|
|
|
if (line)
|
|
|
|
m->setParam("line",line);
|
|
|
|
if (proto)
|
|
|
|
m->setParam("protocol",proto);
|
2005-07-05 21:04:59 +00:00
|
|
|
if (account)
|
|
|
|
m->setParam("account",account);
|
2005-07-04 22:04:47 +00:00
|
|
|
return cc->startRouter(m);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Client::emitDigit(char digit)
|
|
|
|
{
|
|
|
|
Debug(ClientDriver::self(),DebugInfo,"emitDigit('%c')",digit);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Client::callIncoming(const String& caller, const String& dest, Message* msg)
|
|
|
|
{
|
|
|
|
Debug(ClientDriver::self(),DebugAll,"callIncoming [%p]",this);
|
2005-07-27 18:31:47 +00:00
|
|
|
if (m_activeId && !m_multiLines) {
|
|
|
|
if (msg) {
|
|
|
|
msg->setParam("error","busy");
|
|
|
|
msg->setParam("reason","User busy");
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2005-07-04 22:04:47 +00:00
|
|
|
if (msg && msg->userData()) {
|
|
|
|
CallEndpoint* ch = static_cast<CallEndpoint*>(msg->userData());
|
2005-08-13 02:02:55 +00:00
|
|
|
lockOther();
|
2005-07-27 18:31:47 +00:00
|
|
|
ClientChannel* cc = new ClientChannel(caller,ch->id());
|
2005-08-13 02:02:55 +00:00
|
|
|
unlockOther();
|
2005-09-02 16:39:00 +00:00
|
|
|
if (cc->connect(ch,msg->getValue("reason"))) {
|
2005-07-27 18:31:47 +00:00
|
|
|
m_activeId = cc->id();
|
|
|
|
msg->setParam("peerid",m_activeId);
|
|
|
|
msg->setParam("targetid",m_activeId);
|
2005-07-04 22:04:47 +00:00
|
|
|
Engine::enqueue(cc->message("call.ringing",false,true));
|
2005-08-13 02:02:55 +00:00
|
|
|
lockOther();
|
2005-07-04 22:04:47 +00:00
|
|
|
// notify the UI about the call
|
|
|
|
String tmp("Call from:");
|
|
|
|
tmp << " " << caller;
|
|
|
|
setStatus(tmp);
|
2006-01-26 00:00:36 +00:00
|
|
|
setText("incoming",tmp);
|
2006-04-12 12:37:25 +00:00
|
|
|
String* info = msg->getParam("caller_info_uri");
|
2006-04-14 22:50:45 +00:00
|
|
|
if (info && (info->startsWith("http://",false) || info->startsWith("https://",false)))
|
2006-04-12 12:37:25 +00:00
|
|
|
setText("caller_info",*info);
|
|
|
|
info = msg->getParam("caller_icon_uri");
|
2006-04-14 22:50:45 +00:00
|
|
|
if (info && (info->startsWith("http://",false) || info->startsWith("https://",false)))
|
2006-04-12 12:37:25 +00:00
|
|
|
setText("caller_icon",*info);
|
2005-07-27 18:31:47 +00:00
|
|
|
if (m_autoAnswer) {
|
|
|
|
cc->callAnswer();
|
|
|
|
setChannelInternal(cc);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (!(m_multiLines && setVisible("channels")))
|
|
|
|
setVisible("incoming");
|
|
|
|
}
|
2005-08-13 02:02:55 +00:00
|
|
|
unlockOther();
|
2005-07-14 21:41:32 +00:00
|
|
|
cc->deref();
|
2005-07-04 22:04:47 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2006-01-23 15:57:47 +00:00
|
|
|
bool Client::callRouting(const String& caller, const String& called, Message* msg)
|
|
|
|
{
|
|
|
|
// route here all calls by default
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2006-01-30 20:44:03 +00:00
|
|
|
void Client::updateCDR(const Message& msg)
|
|
|
|
{
|
|
|
|
String* dir = msg.getParam("direction");
|
|
|
|
if (!dir)
|
|
|
|
return;
|
|
|
|
String* id = msg.getParam("billid");
|
|
|
|
if (!id || id->null())
|
|
|
|
id = msg.getParam("id");
|
|
|
|
if (!id || id->null())
|
|
|
|
return;
|
|
|
|
String table;
|
|
|
|
// remember, directions are opposite of what the user expects
|
|
|
|
if (*dir == "outgoing")
|
|
|
|
table = "log_incoming";
|
|
|
|
else if (*dir == "incoming")
|
|
|
|
table = "log_outgoing";
|
|
|
|
else
|
|
|
|
return;
|
|
|
|
addTableRow(table,*id,&msg);
|
|
|
|
addTableRow("log_global",*id,&msg);
|
|
|
|
}
|
|
|
|
|
2005-07-27 18:31:47 +00:00
|
|
|
void Client::clearActive(const String& id)
|
2005-07-04 22:04:47 +00:00
|
|
|
{
|
2005-07-27 18:31:47 +00:00
|
|
|
if (id == m_activeId)
|
2006-01-26 00:00:36 +00:00
|
|
|
updateFrom(0);
|
2005-07-04 22:04:47 +00:00
|
|
|
}
|
|
|
|
|
2005-07-14 21:41:32 +00:00
|
|
|
void Client::addChannel(ClientChannel* chan)
|
|
|
|
{
|
2005-07-25 22:44:34 +00:00
|
|
|
addOption("channels",chan->id(),false,chan->description());
|
|
|
|
}
|
|
|
|
|
|
|
|
void Client::setChannel(ClientChannel* chan)
|
|
|
|
{
|
|
|
|
Debug(ClientDriver::self(),DebugAll,"setChannel %p",chan);
|
2006-01-30 20:44:03 +00:00
|
|
|
if (!chan)
|
|
|
|
return;
|
2005-08-13 02:02:55 +00:00
|
|
|
lockOther();
|
2005-07-25 22:44:34 +00:00
|
|
|
setChannelInternal(chan);
|
2005-08-13 02:02:55 +00:00
|
|
|
unlockOther();
|
2005-07-25 22:44:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Client::setChannelInternal(ClientChannel* chan)
|
2006-01-30 20:44:03 +00:00
|
|
|
{
|
|
|
|
setChannelDisplay(chan);
|
|
|
|
bool upd = !m_multiLines;
|
|
|
|
if (!upd) {
|
|
|
|
String tmp;
|
|
|
|
upd = getSelect("channels",tmp) && (tmp == chan->id());
|
|
|
|
}
|
|
|
|
if (upd)
|
|
|
|
updateFrom(chan);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Client::setChannelDisplay(ClientChannel* chan)
|
2005-07-25 22:44:34 +00:00
|
|
|
{
|
2005-07-27 18:31:47 +00:00
|
|
|
String tmp(chan->description());
|
|
|
|
if (!setUrgent(chan->id(),chan->flashing()) && chan->flashing())
|
|
|
|
tmp << " <<<";
|
|
|
|
setText(chan->id(),tmp);
|
2005-07-14 21:41:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Client::delChannel(ClientChannel* chan)
|
|
|
|
{
|
2005-08-13 02:02:55 +00:00
|
|
|
lockOther();
|
2005-07-27 18:31:47 +00:00
|
|
|
clearActive(chan->id());
|
2005-07-14 21:41:32 +00:00
|
|
|
delOption("channels",chan->id());
|
2005-08-13 02:02:55 +00:00
|
|
|
unlockOther();
|
2005-07-14 21:41:32 +00:00
|
|
|
}
|
|
|
|
|
2005-07-27 18:31:47 +00:00
|
|
|
void Client::updateFrom(const String& id)
|
|
|
|
{
|
|
|
|
ClientChannel* chan = 0;
|
|
|
|
if (ClientDriver::self())
|
|
|
|
chan = static_cast<ClientChannel*>(ClientDriver::self()->find(id));
|
|
|
|
if (chan)
|
|
|
|
chan->noticed();
|
|
|
|
updateFrom(chan);
|
|
|
|
}
|
|
|
|
|
2005-07-25 22:44:34 +00:00
|
|
|
void Client::updateFrom(const ClientChannel* chan)
|
|
|
|
{
|
2005-07-27 18:31:47 +00:00
|
|
|
m_activeId = chan ? chan->id() : "";
|
2005-07-25 22:44:34 +00:00
|
|
|
enableAction(chan,"accept");
|
|
|
|
enableAction(chan,"reject");
|
|
|
|
enableAction(chan,"hangup");
|
|
|
|
enableAction(chan,"voicemail");
|
|
|
|
enableAction(chan,"transfer");
|
|
|
|
enableAction(chan,"conference");
|
|
|
|
}
|
|
|
|
|
|
|
|
void Client::enableAction(const ClientChannel* chan, const String& action)
|
|
|
|
{
|
|
|
|
setActive(action,chan && chan->enableAction(action));
|
|
|
|
}
|
|
|
|
|
2005-08-13 02:02:55 +00:00
|
|
|
void Client::idleActions()
|
|
|
|
{
|
2005-10-31 18:22:07 +00:00
|
|
|
if (!s_busy)
|
|
|
|
return;
|
2005-08-13 02:02:55 +00:00
|
|
|
ClientThreadProxy* tmp = s_proxy;
|
|
|
|
s_proxy = 0;
|
|
|
|
if (tmp)
|
|
|
|
tmp->process();
|
|
|
|
}
|
|
|
|
|
2005-08-19 23:21:31 +00:00
|
|
|
bool Client::driverLock(long maxwait)
|
|
|
|
{
|
|
|
|
if (maxwait < 0)
|
|
|
|
maxwait = 0;
|
|
|
|
return ClientDriver::self() && ClientDriver::self()->lock(maxwait);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Client::driverLockLoop()
|
|
|
|
{
|
|
|
|
if (!(isCurrent() && ClientDriver::self()))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
while (!driverLock()) {
|
|
|
|
if (Engine::exiting() || !ClientDriver::self())
|
|
|
|
return false;
|
|
|
|
idleActions();
|
|
|
|
yield();
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Client::driverUnlock()
|
|
|
|
{
|
|
|
|
if (ClientDriver::self())
|
|
|
|
ClientDriver::self()->unlock();
|
|
|
|
}
|
|
|
|
|
2005-08-13 02:02:55 +00:00
|
|
|
|
2006-01-30 20:44:03 +00:00
|
|
|
bool UICdrHandler::received(Message &msg)
|
|
|
|
{
|
|
|
|
if (!Client::self())
|
|
|
|
return false;
|
2006-04-08 18:03:28 +00:00
|
|
|
|
|
|
|
// block until client finishes initialization
|
|
|
|
while (!Client::self()->initialized())
|
|
|
|
Thread::msleep(10);
|
|
|
|
|
2006-01-30 20:44:03 +00:00
|
|
|
String* op = msg.getParam("operation");
|
|
|
|
if (op && (*op == "finalize"))
|
|
|
|
Client::self()->updateCDR(msg);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-04 22:04:47 +00:00
|
|
|
bool UIHandler::received(Message &msg)
|
|
|
|
{
|
|
|
|
if (!Client::self())
|
|
|
|
return false;
|
|
|
|
String action(msg.getValue("action"));
|
|
|
|
if (action.null())
|
|
|
|
return false;
|
2006-04-08 18:03:28 +00:00
|
|
|
|
|
|
|
// block until client finishes initialization
|
|
|
|
while (!Client::self()->initialized())
|
|
|
|
Thread::msleep(10);
|
|
|
|
|
2005-07-04 22:04:47 +00:00
|
|
|
Window* wnd = Client::getWindow(msg.getValue("window"));
|
|
|
|
if (action == "set_status")
|
|
|
|
return Client::self()->setStatusLocked(msg.getValue("status"),wnd);
|
2006-01-26 00:00:36 +00:00
|
|
|
else if (action == "show_message") {
|
|
|
|
Client::self()->lockOther();
|
|
|
|
bool ok = Client::openMessage(msg.getValue("text"),Client::getWindow(msg.getValue("parent")));
|
|
|
|
Client::self()->unlockOther();
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
else if (action == "show_confirm") {
|
|
|
|
Client::self()->lockOther();
|
|
|
|
bool ok = Client::openConfirm(msg.getValue("text"),Client::getWindow(msg.getValue("parent")));
|
|
|
|
Client::self()->unlockOther();
|
|
|
|
return ok;
|
|
|
|
}
|
2005-07-04 22:04:47 +00:00
|
|
|
String name(msg.getValue("name"));
|
|
|
|
if (name.null())
|
|
|
|
return false;
|
|
|
|
DDebug(ClientDriver::self(),DebugAll,"UI action '%s' on '%s' in %p",
|
|
|
|
action.c_str(),name.c_str(),wnd);
|
|
|
|
bool ok = false;
|
2005-08-13 02:02:55 +00:00
|
|
|
Client::self()->lockOther();
|
2005-07-04 22:04:47 +00:00
|
|
|
if (action == "set_text")
|
|
|
|
ok = Client::self()->setText(name,msg.getValue("text"),wnd);
|
|
|
|
else if (action == "set_toggle")
|
|
|
|
ok = Client::self()->setCheck(name,msg.getBoolValue("active"),wnd);
|
|
|
|
else if (action == "set_select")
|
|
|
|
ok = Client::self()->setSelect(name,msg.getValue("item"),wnd);
|
|
|
|
else if (action == "set_active")
|
|
|
|
ok = Client::self()->setActive(name,msg.getBoolValue("active"),wnd);
|
|
|
|
else if (action == "set_visible")
|
|
|
|
ok = Client::self()->setShow(name,msg.getBoolValue("visible"),wnd);
|
2006-04-08 18:03:28 +00:00
|
|
|
else if (action == "has_option")
|
|
|
|
ok = Client::self()->hasOption(name,msg.getValue("item"),wnd);
|
2005-07-04 22:04:47 +00:00
|
|
|
else if (action == "add_option")
|
2005-07-25 22:44:34 +00:00
|
|
|
ok = Client::self()->addOption(name,msg.getValue("item"),msg.getBoolValue("insert"),msg.getValue("text"),wnd);
|
2005-07-04 22:04:47 +00:00
|
|
|
else if (action == "del_option")
|
|
|
|
ok = Client::self()->delOption(name,msg.getValue("item"),wnd);
|
|
|
|
else if (action == "get_text") {
|
|
|
|
String text;
|
|
|
|
ok = Client::self()->getText(name,text,wnd);
|
|
|
|
if (ok)
|
|
|
|
msg.retValue() = text;
|
|
|
|
}
|
|
|
|
else if (action == "get_toggle") {
|
|
|
|
bool check;
|
|
|
|
ok = Client::self()->getCheck(name,check,wnd);
|
|
|
|
if (ok)
|
|
|
|
msg.retValue() = check;
|
|
|
|
}
|
|
|
|
else if (action == "get_select") {
|
|
|
|
String item;
|
|
|
|
ok = Client::self()->getSelect(name,item,wnd);
|
|
|
|
if (ok)
|
|
|
|
msg.retValue() = item;
|
|
|
|
}
|
|
|
|
else if (action == "window_show")
|
|
|
|
ok = Client::setVisible(name,true);
|
|
|
|
else if (action == "window_hide")
|
|
|
|
ok = Client::setVisible(name,false);
|
2005-07-25 22:44:34 +00:00
|
|
|
else if (action == "window_popup")
|
2005-07-27 18:31:47 +00:00
|
|
|
ok = Client::openPopup(name,&msg,Client::getWindow(msg.getValue("parent")));
|
2005-08-13 02:02:55 +00:00
|
|
|
Client::self()->unlockOther();
|
2005-07-04 22:04:47 +00:00
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
2006-04-08 18:03:28 +00:00
|
|
|
|
|
|
|
bool UIUserHandler::received(Message &msg)
|
|
|
|
{
|
|
|
|
if (!Client::self())
|
|
|
|
return false;
|
|
|
|
String account = msg.getValue("account");
|
|
|
|
if (account.null())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// block until client finishes initialization
|
|
|
|
while (!Client::self()->initialized())
|
|
|
|
Thread::msleep(10);
|
|
|
|
|
|
|
|
String op = msg.getParam("operation");
|
|
|
|
if ((op == "create") || (op == "login") || op.null()) {
|
|
|
|
if (!Client::self()->hasOption("accounts",account))
|
|
|
|
Client::self()->addOption("accounts",account,false);
|
|
|
|
if (!Client::self()->hasOption("account",account))
|
|
|
|
Client::self()->addOption("account",account,false);
|
|
|
|
}
|
|
|
|
else if (op == "delete") {
|
|
|
|
Client::self()->delOption("account",account);
|
|
|
|
Client::self()->delOption("accounts",account);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-04 22:04:47 +00:00
|
|
|
// IMPORTANT: having a target means "from inside Yate to the user"
|
|
|
|
// An user initiated call must be incoming (no target)
|
2005-07-27 18:31:47 +00:00
|
|
|
ClientChannel::ClientChannel(const String& party, const char* target)
|
|
|
|
: Channel(ClientDriver::self(),0,(target != 0)),
|
|
|
|
m_party(party), m_line(0), m_flashing(false),
|
2005-07-25 22:44:34 +00:00
|
|
|
m_canAnswer(false), m_canTransfer(false), m_canConference(false)
|
2005-07-04 22:04:47 +00:00
|
|
|
{
|
2005-07-27 18:31:47 +00:00
|
|
|
m_time = Time::now();
|
2005-07-04 22:04:47 +00:00
|
|
|
m_targetid = target;
|
2005-07-27 18:31:47 +00:00
|
|
|
if (target) {
|
|
|
|
m_flashing = true;
|
2005-07-25 22:44:34 +00:00
|
|
|
m_canAnswer = true;
|
2005-07-27 18:31:47 +00:00
|
|
|
}
|
2005-07-25 22:44:34 +00:00
|
|
|
update(false);
|
2005-07-14 21:41:32 +00:00
|
|
|
if (Client::self())
|
|
|
|
Client::self()->addChannel(this);
|
2005-07-04 22:04:47 +00:00
|
|
|
Engine::enqueue(message("chan.startup"));
|
|
|
|
}
|
|
|
|
|
|
|
|
ClientChannel::~ClientChannel()
|
|
|
|
{
|
|
|
|
closeMedia();
|
|
|
|
String tmp("Hung up:");
|
|
|
|
tmp << " " << (address() ? address() : id());
|
|
|
|
if (Client::self()) {
|
2005-07-14 21:41:32 +00:00
|
|
|
Client::self()->delChannel(this);
|
2005-07-04 22:04:47 +00:00
|
|
|
Client::self()->setStatusLocked(tmp);
|
|
|
|
}
|
|
|
|
Engine::enqueue(message("chan.hangup"));
|
|
|
|
}
|
|
|
|
|
2005-07-12 16:05:29 +00:00
|
|
|
bool ClientChannel::openMedia(bool replace)
|
2005-07-04 22:04:47 +00:00
|
|
|
{
|
|
|
|
String dev = ClientDriver::device();
|
|
|
|
if (dev.null())
|
|
|
|
return false;
|
2005-07-12 16:05:29 +00:00
|
|
|
if ((!replace) && getSource() && getConsumer())
|
|
|
|
return true;
|
2005-07-04 22:04:47 +00:00
|
|
|
Message m("chan.attach");
|
|
|
|
complete(m,true);
|
|
|
|
m.setParam("source",dev);
|
|
|
|
m.setParam("consumer",dev);
|
|
|
|
m.userData(this);
|
|
|
|
return Engine::dispatch(m);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ClientChannel::closeMedia()
|
|
|
|
{
|
|
|
|
setSource();
|
|
|
|
setConsumer();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ClientChannel::line(int newLine)
|
|
|
|
{
|
|
|
|
m_line = newLine;
|
|
|
|
m_address.clear();
|
|
|
|
if (m_line > 0)
|
|
|
|
m_address << "line/" << m_line;
|
|
|
|
}
|
|
|
|
|
2005-07-25 22:44:34 +00:00
|
|
|
void ClientChannel::update(bool client)
|
|
|
|
{
|
2005-07-27 18:31:47 +00:00
|
|
|
String desc;
|
|
|
|
if (m_canAnswer)
|
|
|
|
desc = "Ringing";
|
|
|
|
// directions are from engine's perspective so reverse them for user
|
|
|
|
else if (isOutgoing())
|
|
|
|
desc = "Incoming";
|
|
|
|
else desc = "Outgoing";
|
|
|
|
desc << " " << m_party;
|
|
|
|
unsigned int sec = (unsigned int)((Time::now() - m_time + 500000) / 1000000);
|
|
|
|
char buf[32];
|
|
|
|
::snprintf(buf,sizeof(buf)," [%02u:%02u:%02u]",sec/3600,(sec/60)%60,sec%60);
|
|
|
|
desc << buf;
|
2005-07-25 22:44:34 +00:00
|
|
|
CallEndpoint* peer = getPeer();
|
|
|
|
if (peer) {
|
|
|
|
peer->ref();
|
|
|
|
String tmp;
|
|
|
|
if (peer->getConsumer())
|
|
|
|
tmp = peer->getConsumer()->getFormat();
|
|
|
|
if (tmp.null())
|
|
|
|
tmp = "-";
|
2005-07-27 18:31:47 +00:00
|
|
|
desc << " [" << tmp;
|
2005-07-25 22:44:34 +00:00
|
|
|
tmp.clear();
|
|
|
|
if (peer->getSource())
|
|
|
|
tmp = peer->getSource()->getFormat();
|
|
|
|
peer->deref();
|
|
|
|
if (tmp.null())
|
|
|
|
tmp = "-";
|
2005-07-27 18:31:47 +00:00
|
|
|
desc << "/" << tmp << "]";
|
2005-07-25 22:44:34 +00:00
|
|
|
}
|
2005-07-27 18:31:47 +00:00
|
|
|
desc << " " << id();
|
|
|
|
m_desc = desc;
|
|
|
|
XDebug(ClientDriver::self(),DebugAll,"update %d '%s'",client,desc.c_str());
|
2005-07-25 22:44:34 +00:00
|
|
|
if (client && Client::self())
|
|
|
|
Client::self()->setChannel(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ClientChannel::enableAction(const String& action) const
|
|
|
|
{
|
|
|
|
if (action == "hangup")
|
|
|
|
return true;
|
|
|
|
else if ((action == "accept") || (action == "reject") || (action == "voicemail"))
|
|
|
|
return m_canAnswer;
|
|
|
|
else if (action == "transfer")
|
|
|
|
return m_canTransfer;
|
|
|
|
else if (action == "conference")
|
|
|
|
return m_canConference;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2005-07-04 22:04:47 +00:00
|
|
|
bool ClientChannel::callRouted(Message& msg)
|
|
|
|
{
|
|
|
|
String tmp("Calling:");
|
|
|
|
tmp << " " << msg.retValue();
|
|
|
|
Client::self()->setStatusLocked(tmp);
|
2005-07-25 22:44:34 +00:00
|
|
|
update();
|
2005-07-04 22:04:47 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ClientChannel::callAccept(Message& msg)
|
|
|
|
{
|
|
|
|
Debug(ClientDriver::self(),DebugAll,"ClientChannel::callAccept() [%p]",this);
|
|
|
|
Client::self()->setStatusLocked("Call connected");
|
|
|
|
Channel::callAccept(msg);
|
2005-07-25 22:44:34 +00:00
|
|
|
update();
|
2005-07-04 22:04:47 +00:00
|
|
|
}
|
|
|
|
|
2005-07-12 16:05:29 +00:00
|
|
|
void ClientChannel::callRejected(const char* error, const char* reason, const Message* msg)
|
2005-07-04 22:04:47 +00:00
|
|
|
{
|
2005-07-12 16:05:29 +00:00
|
|
|
Debug(ClientDriver::self(),DebugAll,"ClientChannel::callReject('%s','%s',%p) [%p]",
|
|
|
|
error,reason,msg,this);
|
2005-07-04 22:04:47 +00:00
|
|
|
if (!reason)
|
|
|
|
reason = error;
|
|
|
|
if (!reason)
|
|
|
|
reason = "Unknown reason";
|
|
|
|
String tmp("Call failed:");
|
|
|
|
tmp << " " << reason;
|
|
|
|
if (Client::self())
|
|
|
|
Client::self()->setStatusLocked(tmp);
|
2005-07-12 16:05:29 +00:00
|
|
|
Channel::callRejected(error,reason,msg);
|
2005-07-27 18:31:47 +00:00
|
|
|
m_flashing = true;
|
2005-07-25 22:44:34 +00:00
|
|
|
m_canConference = m_canTransfer = m_canAnswer = false;
|
|
|
|
update();
|
2005-07-12 16:05:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool ClientChannel::msgProgress(Message& msg)
|
|
|
|
{
|
|
|
|
Debug(ClientDriver::self(),DebugAll,"ClientChannel::msgProgress() [%p]",this);
|
|
|
|
Client::self()->setStatusLocked("Call progressing");
|
|
|
|
CallEndpoint *ch = static_cast<CallEndpoint*>(msg.userObject("CallEndpoint"));
|
|
|
|
if (ch && ch->getSource())
|
|
|
|
openMedia();
|
2005-07-25 22:44:34 +00:00
|
|
|
bool ret = Channel::msgProgress(msg);
|
|
|
|
update();
|
|
|
|
return ret;
|
2005-07-04 22:04:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool ClientChannel::msgRinging(Message& msg)
|
|
|
|
{
|
|
|
|
Debug(ClientDriver::self(),DebugAll,"ClientChannel::msgRinging() [%p]",this);
|
|
|
|
Client::self()->setStatusLocked("Call ringing");
|
2005-07-12 16:05:29 +00:00
|
|
|
CallEndpoint *ch = static_cast<CallEndpoint*>(msg.userObject("CallEndpoint"));
|
|
|
|
if (ch && ch->getSource())
|
|
|
|
openMedia();
|
2005-07-25 22:44:34 +00:00
|
|
|
bool ret = Channel::msgRinging(msg);
|
|
|
|
update();
|
|
|
|
return ret;
|
2005-07-04 22:04:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool ClientChannel::msgAnswered(Message& msg)
|
|
|
|
{
|
|
|
|
Debug(ClientDriver::self(),DebugAll,"ClientChannel::msgAnswered() [%p]",this);
|
2005-07-27 18:31:47 +00:00
|
|
|
m_time = Time::now();
|
|
|
|
m_flashing = true;
|
2005-07-25 22:44:34 +00:00
|
|
|
m_canAnswer = false;
|
|
|
|
m_canConference = true;
|
|
|
|
m_canTransfer = true;
|
2005-07-04 22:04:47 +00:00
|
|
|
Client::self()->setStatusLocked("Call answered");
|
|
|
|
openMedia();
|
2005-07-25 22:44:34 +00:00
|
|
|
bool ret = Channel::msgAnswered(msg);
|
|
|
|
update();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ClientChannel::callAnswer()
|
|
|
|
{
|
|
|
|
Debug(ClientDriver::self(),DebugAll,"ClientChannel::callAnswer() [%p]",this);
|
2005-07-27 18:31:47 +00:00
|
|
|
m_time = Time::now();
|
|
|
|
m_flashing = false;
|
2005-07-25 22:44:34 +00:00
|
|
|
m_canAnswer = false;
|
|
|
|
m_canConference = true;
|
|
|
|
m_canTransfer = true;
|
|
|
|
status("answered");
|
|
|
|
Client::self()->setStatus("Call answered");
|
|
|
|
openMedia();
|
|
|
|
update(false);
|
|
|
|
Engine::enqueue(message("call.answered",false,true));
|
2005-07-04 22:04:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ClientDriver* ClientDriver::s_driver = 0;
|
|
|
|
String ClientDriver::s_device;
|
|
|
|
|
|
|
|
ClientDriver::ClientDriver()
|
|
|
|
: Driver("client","misc")
|
|
|
|
{
|
|
|
|
s_driver = this;
|
|
|
|
}
|
|
|
|
|
|
|
|
ClientDriver::~ClientDriver()
|
|
|
|
{
|
|
|
|
s_driver = 0;
|
|
|
|
}
|
|
|
|
|
2005-07-25 22:44:34 +00:00
|
|
|
void ClientDriver::setup()
|
|
|
|
{
|
|
|
|
Driver::setup();
|
|
|
|
installRelay(Halt);
|
|
|
|
installRelay(Progress);
|
2006-01-23 15:57:47 +00:00
|
|
|
installRelay(Route,200);
|
2005-07-25 22:44:34 +00:00
|
|
|
}
|
|
|
|
|
2005-07-04 22:04:47 +00:00
|
|
|
bool ClientDriver::factory(UIFactory* factory, const char* type)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ClientDriver::msgExecute(Message& msg, String& dest)
|
|
|
|
{
|
|
|
|
Debug(this,DebugInfo,"msgExecute() '%s'",dest.c_str());
|
|
|
|
return (Client::self()) && (Client::self()->callIncoming(msg.getValue("caller"),dest,&msg));
|
|
|
|
}
|
|
|
|
|
2005-07-27 18:31:47 +00:00
|
|
|
void ClientDriver::msgTimer(Message& msg)
|
|
|
|
{
|
|
|
|
Driver::msgTimer(msg);
|
|
|
|
if (Client::self()) {
|
2005-08-13 02:02:55 +00:00
|
|
|
Client::self()->lockOther();
|
2005-07-27 18:31:47 +00:00
|
|
|
ObjList* l = &channels();
|
|
|
|
for (; l; l = l->next()) {
|
|
|
|
ClientChannel* cc = static_cast<ClientChannel*>(l->get());
|
|
|
|
if (cc) {
|
|
|
|
cc->update(false);
|
|
|
|
Client::self()->setChannelInternal(cc);
|
|
|
|
}
|
|
|
|
}
|
2005-08-13 02:02:55 +00:00
|
|
|
Client::self()->unlockOther();
|
2005-07-27 18:31:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-01-23 15:57:47 +00:00
|
|
|
bool ClientDriver::msgRoute(Message& msg)
|
|
|
|
{
|
|
|
|
// don't route here our own calls
|
|
|
|
if (name() == msg.getValue("module"))
|
|
|
|
return false;
|
|
|
|
if (Client::self() && Client::self()->callRouting(msg.getValue("caller"),msg.getValue("called"),&msg)) {
|
|
|
|
msg.retValue() = name() + "/*";
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2005-07-04 22:04:47 +00:00
|
|
|
ClientChannel* ClientDriver::findLine(int line)
|
|
|
|
{
|
|
|
|
if (line < 1)
|
|
|
|
return 0;
|
|
|
|
Lock mylock(this);
|
|
|
|
ObjList* l = &channels();
|
|
|
|
for (; l; l = l->next()) {
|
|
|
|
ClientChannel* cc = static_cast<ClientChannel*>(l->get());
|
|
|
|
if (cc && (cc->line() == line))
|
|
|
|
return cc;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vi: set ts=8 sw=4 sts=4 noet: */
|