Added support for proper handling of call history.

git-svn-id: http://yate.null.ro/svn/yate/trunk@776 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
paulc 2006-05-08 21:59:42 +00:00
parent 9b40ddc480
commit 8e639a1747
3 changed files with 119 additions and 18 deletions

View File

@ -389,6 +389,13 @@ static gboolean widgetCbShow(GtkWidget* wid, gpointer dat)
return GTKClient::setVisible(name);
}
static gboolean widgetCbChanged(GtkRange* range, gpointer dat)
{
const gchar* name = gtk_widget_get_name((GtkWidget*)range);
Debug(GTKDriver::self(),DebugAll,"widgetCbChanged(%p,%p) '%s'",range,dat,name);
return FALSE;
}
static gboolean widgetCbSwitch(GtkNotebook* nbk, GtkNotebookPage* page, guint page_num, gpointer dat)
{
const gchar* name = gtk_widget_get_name(GTK_WIDGET(nbk));
@ -616,6 +623,16 @@ static GtkWidget* gtkTableNew(const gchar* text)
return table;
}
static GtkWidget* gtkHscaleNew(const gchar* text)
{
return gtk_hscale_new_with_range(0,100,10);
}
static GtkWidget* gtkVscaleNew(const gchar* text)
{
return gtk_vscale_new_with_range(0,100,10);
}
static WidgetMaker s_widgetMakers[] = {
{ "label", gtkLeftLabelNew, 0, 0 },
{ "editor", gtkEntryNewWithText, "activate", G_CALLBACK(widgetCbAction) },
@ -635,6 +652,8 @@ static WidgetMaker s_widgetMakers[] = {
{ "button_icon", gtkButtonNew, "clicked", G_CALLBACK(widgetCbMinimize) },
{ "button_hide", gtkButtonNew, "clicked", G_CALLBACK(widgetCbHide) },
{ "button_max", gtkButtonNew, "clicked", G_CALLBACK(widgetCbMaximize) },
{ "hscale", gtkHscaleNew, "value-changed", G_CALLBACK(widgetCbChanged) },
{ "vscale", gtkVscaleNew, "value-changed", G_CALLBACK(widgetCbChanged) },
{ 0, 0, 0, 0 },
};
// { "", gtk__new, "", },
@ -1315,6 +1334,10 @@ bool GTKWindow::setText(GtkWidget* wid, const String& text)
gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(wid)->entry),text.safe());
return true;
}
if (GTK_IS_ADJUSTMENT(wid)) {
gtk_adjustment_set_value(GTK_ADJUSTMENT(wid),text.toDouble());
return true;
}
return false;
}

View File

@ -371,6 +371,7 @@ int Client::s_changing = 0;
static Configuration s_accounts;
static Configuration s_contacts;
static Configuration s_providers;
static Configuration s_history;
// Parameters that are stored with account
static const char* s_accParams[] = {
@ -523,6 +524,15 @@ void Client::initClient()
}
}
s_history = Engine::configFile("client_history");
s_history.load();
n = s_history.sections();
for (i=0; i<n; i++) {
NamedList* sect = s_history.getSection(i);
if (sect)
updateCallHist(*sect);
}
bool tmp =
getWindow("channels") || hasElement("channels") ||
getWindow("lines") || hasElement("lines");
@ -1148,8 +1158,21 @@ bool Client::action(Window* wnd, const String& name)
}
// outgoing (placed) call log actions
else if (name == "log_out_clear") {
if (clearTable("log_outgoing"))
if (clearTable("log_outgoing")) {
for (unsigned int i = 0; i < s_history.sections(); i++) {
NamedList* sect = s_history.getSection(i);
if (!sect)
continue;
String* dir = sect->getParam("direction");
// directions are backwards
if (dir && (*dir == "incoming")) {
s_history.clearSection(*sect);
i--;
}
}
s_history.save();
return true;
}
}
else if ((name == "log_out_call") || (name == "log_outgoing")) {
NamedList log("");
@ -1163,8 +1186,21 @@ bool Client::action(Window* wnd, const String& name)
}
// incoming (received) call log actions
else if (name == "log_in_clear") {
if (clearTable("log_incoming"))
if (clearTable("log_incoming")) {
for (unsigned int i = 0; i < s_history.sections(); i++) {
NamedList* sect = s_history.getSection(i);
if (!sect)
continue;
String* dir = sect->getParam("direction");
// directions are backwards, remember?
if (dir && (*dir == "outgoing")) {
s_history.clearSection(*sect);
i--;
}
}
s_history.save();
return true;
}
}
else if ((name == "log_in_call") || (name == "log_incoming")) {
NamedList log("");
@ -1178,8 +1214,11 @@ bool Client::action(Window* wnd, const String& name)
}
// mixed call log actions
else if (name == "log_clear") {
if (clearTable("log_global"))
if (clearTable("log_global")) {
s_history.clearSection();
s_history.save();
return true;
}
}
// unknown/unhandled - generate a message for them
@ -1380,7 +1419,7 @@ bool Client::callIncoming(const String& caller, const String& dest, Message* msg
if (msg && msg->userData()) {
CallEndpoint* ch = static_cast<CallEndpoint*>(msg->userData());
lockOther();
ClientChannel* cc = new ClientChannel(caller,ch->id());
ClientChannel* cc = new ClientChannel(caller,ch->id(),msg);
unlockOther();
if (cc->connect(ch,msg->getValue("reason"))) {
m_activeId = cc->id();
@ -1423,14 +1462,40 @@ bool Client::callRouting(const String& caller, const String& called, Message* ms
void Client::updateCDR(const Message& msg)
{
String* dir = msg.getParam("direction");
if (!dir)
if (!updateCallHist(msg))
return;
String* id = msg.getParam("billid");
if (!id || id->null())
String id = msg.getParam("billid");
if (id.null())
id = msg.getParam("id");
if (!id || id->null())
// it worked before - but paranoia can be fun
if (id.null())
return;
while (s_history.sections() >= 20) {
NamedList* sect = s_history.getSection(0);
if (!sect)
break;
s_history.clearSection(*sect);
}
unsigned int n = msg.length();
for (unsigned int i = 0; i < n; i++) {
NamedString* param = msg.getParam(i);
if (!param)
continue;
s_history.setValue(id,param->name(),param->c_str());
}
s_history.save();
}
bool Client::updateCallHist(const NamedList& params)
{
String* dir = params.getParam("direction");
if (!dir)
return false;
String* id = params.getParam("billid");
if (!id || id->null())
id = params.getParam("id");
if (!id || id->null())
return false;
String table;
// remember, directions are opposite of what the user expects
if (*dir == "outgoing")
@ -1438,9 +1503,10 @@ void Client::updateCDR(const Message& msg)
else if (*dir == "incoming")
table = "log_outgoing";
else
return;
addTableRow(table,*id,&msg);
addTableRow("log_global",*id,&msg);
return false;
bool ok = addTableRow(table,*id,&params);
ok = addTableRow("log_global",*id,&params) || ok;
return ok;
}
void Client::clearActive(const String& id)
@ -1562,13 +1628,18 @@ bool UICdrHandler::received(Message &msg)
if (!Client::self())
return false;
String* op = msg.getParam("operation");
if (!(op && (*op == "finalize")))
return false;
op = msg.getParam("chan");
if (!(op && op->startsWith("client/",false)))
return false;
// block until client finishes initialization
while (!Client::self()->initialized())
Thread::msleep(10);
String* op = msg.getParam("operation");
if (op && (*op == "finalize"))
Client::self()->updateCDR(msg);
Client::self()->updateCDR(msg);
return false;
}
@ -1681,7 +1752,7 @@ bool UIUserHandler::received(Message &msg)
// IMPORTANT: having a target means "from inside Yate to the user"
// An user initiated call must be incoming (no target)
ClientChannel::ClientChannel(const String& party, const char* target)
ClientChannel::ClientChannel(const String& party, const char* target, const Message* msg)
: Channel(ClientDriver::self(),0,(target != 0)),
m_party(party), m_line(0), m_flashing(false),
m_canAnswer(false), m_canTransfer(false), m_canConference(false)
@ -1695,7 +1766,13 @@ ClientChannel::ClientChannel(const String& party, const char* target)
update(false);
if (Client::self())
Client::self()->addChannel(this);
Engine::enqueue(message("chan.startup"));
Message* s = message("chan.startup");
if (msg) {
s->setParam("caller",msg->getValue("caller"));
s->setParam("called",msg->getValue("called"));
s->setParam("billid",msg->getValue("billid"));
}
Engine::enqueue(s);
}
ClientChannel::~ClientChannel()

View File

@ -341,6 +341,7 @@ protected:
virtual void initWindows();
virtual void initClient();
virtual void setChannelDisplay(ClientChannel* chan);
virtual bool updateCallHist(const NamedList& params);
void addChannel(ClientChannel* chan);
void delChannel(ClientChannel* chan);
void setChannel(ClientChannel* chan);
@ -372,7 +373,7 @@ class YATE_API ClientChannel : public Channel
{
friend class ClientDriver;
public:
ClientChannel(const String& party, const char* target = 0);
ClientChannel(const String& party, const char* target = 0, const Message* msg = 0);
virtual ~ClientChannel();
virtual bool msgProgress(Message& msg);
virtual bool msgRinging(Message& msg);