Added skinnable Gtk2 client.
git-svn-id: http://yate.null.ro/svn/yate/trunk@429 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
80109fdfb4
commit
d1c8926c82
|
@ -20,7 +20,7 @@ MKDEPS := ./config.status
|
|||
PROGS:= yate
|
||||
YLIB := libyate.so.@PACKAGE_VERSION@
|
||||
SLIBS:= $(YLIB) libyate.so
|
||||
INCS := yateclass.h yatengine.h yatephone.h
|
||||
INCS := yateclass.h yatengine.h yatephone.h yatecbase.h
|
||||
GENS := yateversn.h
|
||||
LIBS :=
|
||||
MAN8 := yate.8 yate-config.8
|
||||
|
@ -86,7 +86,9 @@ apidocs-build: check-topdir
|
|||
|
||||
apidocs: @srcdir@/docs/api/index.html
|
||||
|
||||
@srcdir@/docs/api/index.html: @srcdir@/yateclass.h @srcdir@/yatengine.h @srcdir@/yatephone.h @srcdir@/contrib/ysip/yatesip.h @srcdir@/contrib/yrtp/yatertp.h
|
||||
@srcdir@/docs/api/index.html: @srcdir@/yateclass.h @srcdir@/yatengine.h \
|
||||
@srcdir@/yatephone.h @srcdir@/yatecbase.h \
|
||||
@srcdir@/contrib/ysip/yatesip.h @srcdir@/contrib/yrtp/yatertp.h
|
||||
$(MAKE) apidocs-build
|
||||
|
||||
.PHONY: strip sex love war
|
||||
|
|
|
@ -29,6 +29,10 @@ ifneq (@HAVE_QT@,no)
|
|||
PROGS := $(PROGS) yate-qt
|
||||
endif
|
||||
|
||||
ifneq (@HAVE_GTK2@,no)
|
||||
PROGS := $(PROGS) yate-gtk2
|
||||
endif
|
||||
|
||||
LOCALFLAGS =
|
||||
LOCALLIBS =
|
||||
COMPILE = $(CXX) $(DEFS) $(DEBUG) $(INCLUDES) $(CFLAGS)
|
||||
|
@ -86,9 +90,16 @@ yate-%: @srcdir@/main-%.cpp $(MKDEPS) ../libyate.so $(INCFILES)
|
|||
yate-gtk: LOCALFLAGS = @GTK_INC@
|
||||
yate-gtk: LOCALLIBS = @GTK_LIB@
|
||||
|
||||
yate-gtk2: ../contrib/gtk2/libgtk2client.a
|
||||
yate-gtk2: LOCALFLAGS = @GTK2_INC@
|
||||
yate-gtk2: LOCALLIBS = ../contrib/gtk2/libgtk2client.a @GTK2_LIB@
|
||||
|
||||
yate-qt: ../contrib/qt/libqtclientform.a
|
||||
yate-qt: LOCALFLAGS = -I@QT_INC@
|
||||
yate-qt: LOCALLIBS = ../contrib/qt/libqtclientform.a -L@QT_DIR@/lib -lqt-mt
|
||||
|
||||
../contrib/qt/libqtclientform.a:
|
||||
$(MAKE) -C ../contrib/qt
|
||||
|
||||
../contrib/gtk2/libgtk2client.a:
|
||||
$(MAKE) -C ../contrib/gtk2
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* main-gtk2.cpp
|
||||
* This file is part of the YATE Project http://YATE.null.ro
|
||||
*
|
||||
* A Gtk-2 based universal telephony client
|
||||
*
|
||||
* 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 <yatephone.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include "../contrib/gtk2/gtk2client.h"
|
||||
|
||||
using namespace TelEngine;
|
||||
|
||||
static GTKDriver gtkdriver;
|
||||
|
||||
extern "C" int main(int argc, const char** argv, const char** environ)
|
||||
{
|
||||
g_thread_init(NULL);
|
||||
gdk_threads_init();
|
||||
bool fail = !gtk_init_check(&argc,(char ***)&argv);
|
||||
if (fail)
|
||||
g_warning("Cannot open display: '%s'",gdk_get_display());
|
||||
TelEngine::Engine::extraPath() = "gtk2";
|
||||
return TelEngine::Engine::main(argc,argv,environ,TelEngine::Engine::Client,fail);
|
||||
}
|
||||
/* vi: set ts=8 sw=4 sts=4 noet: */
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Script to run the Gtk2 client from the build directory
|
||||
|
||||
if [ -x yate-gtk2 -a -x ../run ]; then
|
||||
# Need to put the path to Mozilla libraries here
|
||||
export LD_LIBRARY_PATH=/usr/lib/mozilla-1.6
|
||||
cd ..; exec ./run --executable clients/yate-gtk2 "$@"
|
||||
else
|
||||
echo "Could not find client executable or run script" >&2
|
||||
fi
|
59
configure.in
59
configure.in
|
@ -203,6 +203,21 @@ fi
|
|||
AC_SUBST(HAVE_GSM)
|
||||
AC_SUBST(GSM_INC)
|
||||
|
||||
HAVE_ILBC=no
|
||||
AC_ARG_ENABLE(ilbc,AC_HELP_STRING([--enable-ilbc],[Enable iLBC codec]),want_ilbc=$enableval,want_ilbc=yes)
|
||||
if [[ "x$want_ilbc" = "xyes" ]]; then
|
||||
HAVE_ILBC=yes
|
||||
fi
|
||||
AC_MSG_CHECKING([for iLBC in contrib])
|
||||
inci10="contrib/ilbc"
|
||||
if [[ -f "$basedir/$inci10/iLBC_encode.h" ]]; then
|
||||
HAVE_ILBC=yes
|
||||
ILBC_INC="-I$basedir/$inci2"
|
||||
ILBC_DEP="../$inci2/libiax.a"
|
||||
fi
|
||||
AC_MSG_RESULT([$HAVE_ILBC])
|
||||
AC_SUBST(HAVE_ILBC)
|
||||
|
||||
HAVE_PWLIB=no
|
||||
PWLIB_RTTI=none
|
||||
PWLIB_INC=""
|
||||
|
@ -465,6 +480,49 @@ AC_SUBST(HAVE_GTK)
|
|||
AC_SUBST(GTK_INC)
|
||||
AC_SUBST(GTK_LIB)
|
||||
|
||||
HAVE_GTK2=no
|
||||
GTK2_INC=""
|
||||
GTK2_LIB=""
|
||||
AC_ARG_WITH(libgtk2,AC_HELP_STRING([--with-libgtk2],[use Gtk for graphical clients (default)]),[ac_cv_use_libgtk2=$withval],[ac_cv_use_libgtk2=yes])
|
||||
if [[ "x$ac_cv_use_libgtk2" = "xyes" ]]; then
|
||||
AC_MSG_CHECKING([for Gtk2 using pkg-config])
|
||||
vergt=`pkg-config --modversion gtk+-2.0 2>/dev/null`
|
||||
incgt=`pkg-config --cflags gtk+-2.0 gthread-2.0 2>/dev/null`
|
||||
libgt=`pkg-config --libs gtk+-2.0 gthread-2.0 2>/dev/null`
|
||||
if [[ "x$incgt" != "x" -a "x$libgt" != "x" ]]; then
|
||||
HAVE_GTK2=yes
|
||||
GTK2_INC="$incgt"
|
||||
GTK2_LIB="$libgt"
|
||||
ac_cv_use_libgtk2="no"
|
||||
fi
|
||||
AC_MSG_RESULT([$vergt])
|
||||
fi
|
||||
AC_SUBST(HAVE_GTK2)
|
||||
AC_SUBST(GTK2_INC)
|
||||
AC_SUBST(GTK2_LIB)
|
||||
|
||||
HAVE_GMOZ=no
|
||||
GMOZ_INC=""
|
||||
GMOZ_LIB=""
|
||||
AC_ARG_WITH(gtkmozilla,AC_HELP_STRING([--with-gtkmozilla],[use Mozilla embedded in Gtk clients (default)]),[ac_cv_use_gtkmozilla=$withval],[ac_cv_use_gtkmozilla=yes])
|
||||
if [[ "x$ac_cv_use_gtkmozilla" = "xyes" ]]; then
|
||||
AC_MSG_CHECKING([for Gtk Mozilla embedding using pkg-config])
|
||||
vergmoz=`pkg-config --modversion mozilla-gtkmozembed 2>/dev/null`
|
||||
incgmoz=`pkg-config --cflags mozilla-gtkmozembed 2>/dev/null`
|
||||
libgmoz=`pkg-config --libs mozilla-gtkmozembed 2>/dev/null`
|
||||
if [[ "x$incgmoz" != "x" -a "x$libgmoz" != "x" ]]; then
|
||||
HAVE_GMOZ=yes
|
||||
GMOZ_INC="$incgmoz"
|
||||
GMOZ_LIB="$libgmoz"
|
||||
ac_cv_use_gtkmozilla="no"
|
||||
fi
|
||||
AC_MSG_RESULT([$vergmoz])
|
||||
fi
|
||||
AC_SUBST(HAVE_GMOZ)
|
||||
AC_SUBST(GMOZ_INC)
|
||||
AC_SUBST(GMOZ_LIB)
|
||||
|
||||
|
||||
HAVE_QT=no
|
||||
QT_DIR=""
|
||||
QT_INC=""
|
||||
|
@ -552,6 +610,7 @@ AC_CONFIG_FILES([yate.spec
|
|||
contrib/ysip/Makefile
|
||||
contrib/yrtp/Makefile
|
||||
contrib/qt/Makefile
|
||||
contrib/gtk2/Makefile
|
||||
test/Makefile])
|
||||
AC_CONFIG_FILES([yate-config],[chmod +x yate-config])
|
||||
AC_CONFIG_FILES([run],[chmod +x run])
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
Makefile
|
||||
core*
|
||||
*.o
|
||||
*.a
|
||||
*.orig
|
||||
*~
|
||||
.*.swp
|
|
@ -0,0 +1,38 @@
|
|||
# Makefile
|
||||
# This file holds the make rules for the Gtk2 client support
|
||||
|
||||
CXX := @CXX@ -Wall
|
||||
AR := ar
|
||||
DEFS:=
|
||||
|
||||
INCLUDES:=-I. -I@srcdir@ -I@top_srcdir@ @GTK2_INC@
|
||||
CXXFLAGS:=$(CXXFLAGS) @MODULE_CPPFLAGS@ @INLINE_FLAGS@
|
||||
LDFLAGS:= -L../.. -lyate
|
||||
INCFILES := @top_srcdir@/yateclass.h @top_srcdir@/yatecbase.h @srcdir@/gtk2client.h
|
||||
MODFLAGS:= @MODULE_LDFLAGS@
|
||||
MODSTRIP:= @MODULE_SYMBOLS@
|
||||
|
||||
PROJECT = libgtk2client.a
|
||||
SOURCES = gtk2client.cpp
|
||||
OBJECTS = $(SOURCES:.cpp=.o)
|
||||
|
||||
COMPILE = $(CXX) $(DEFS) $(INCLUDES) $(CXXFLAGS)
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: $(PROJECT)
|
||||
|
||||
clean:
|
||||
@-$(RM) $(PROJECT) $(OBJECTS)
|
||||
|
||||
$(PROJECT): $(OBJECTS)
|
||||
$(AR) rcs $@ $^
|
||||
|
||||
%.o: @srcdir@/%.cpp $(INCFILES)
|
||||
$(COMPILE) -c $<
|
||||
|
||||
Makefile: @srcdir@/Makefile.in ../../config.status
|
||||
cd ../.. && ./config.status
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,205 @@
|
|||
/**
|
||||
* gtk2client.h
|
||||
* This file is part of the YATE Project http://YATE.null.ro
|
||||
*
|
||||
* A Gtk based universal telephony client
|
||||
*
|
||||
* 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>
|
||||
|
||||
#ifdef _WINDOWS
|
||||
|
||||
#ifdef LIBYGTK2_EXPORTS
|
||||
#define YGTK2_API __declspec(dllexport)
|
||||
#else
|
||||
#ifndef LIBYGTK2_STATIC
|
||||
#define YGTK2_API __declspec(dllimport)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* _WINDOWS */
|
||||
|
||||
#ifndef YGTK2_API
|
||||
#define YGTK2_API
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
namespace TelEngine {
|
||||
|
||||
class YGTK2_API GTKClient : public Client
|
||||
{
|
||||
friend class GTKWindow;
|
||||
public:
|
||||
GTKClient();
|
||||
virtual ~GTKClient();
|
||||
virtual void main();
|
||||
virtual void lock();
|
||||
virtual void unlock();
|
||||
virtual void allHidden();
|
||||
virtual bool createWindow(const String& name);
|
||||
protected:
|
||||
virtual void loadWindows();
|
||||
};
|
||||
|
||||
class YGTK2_API GTKDriver : public ClientDriver
|
||||
{
|
||||
public:
|
||||
GTKDriver();
|
||||
virtual ~GTKDriver();
|
||||
virtual void initialize();
|
||||
virtual bool factory(UIFactory* factory, const char* type = 0);
|
||||
};
|
||||
|
||||
class YGTK2_API Widget
|
||||
{
|
||||
public:
|
||||
Widget();
|
||||
virtual ~Widget();
|
||||
inline GtkWidget* widget() const
|
||||
{ return m_widget; }
|
||||
virtual bool setText(const String& text);
|
||||
virtual bool setCheck(bool checked);
|
||||
virtual bool setSelect(const String& item);
|
||||
virtual bool addOption(const String& item, bool atStart = false);
|
||||
virtual bool delOption(const String& item);
|
||||
virtual bool getText(String& text);
|
||||
virtual bool getCheck(bool& checked);
|
||||
protected:
|
||||
void widget(GtkWidget* wid);
|
||||
private:
|
||||
GtkWidget* m_widget;
|
||||
void destroyed();
|
||||
static void destroyCb(GtkObject* obj, gpointer dat);
|
||||
};
|
||||
|
||||
class YGTK2_API GTKWindow : public Window
|
||||
{
|
||||
friend class GTKClient;
|
||||
public:
|
||||
enum Layout {
|
||||
Unknown = 0,
|
||||
Fixed,
|
||||
Table,
|
||||
Infinite,
|
||||
HBox,
|
||||
VBox,
|
||||
Boxed,
|
||||
Tabbed,
|
||||
Framed,
|
||||
};
|
||||
GTKWindow(const char* id = 0, Layout layout = Unknown);
|
||||
virtual ~GTKWindow();
|
||||
virtual bool setActive(const String& name, bool active);
|
||||
virtual bool setShow(const String& name, bool visible);
|
||||
virtual bool setText(const String& name, const String& text);
|
||||
virtual bool setCheck(const String& name, bool checked);
|
||||
virtual bool setSelect(const String& name, const String& item);
|
||||
virtual bool addOption(const String& name, const String& item, bool atStart = false);
|
||||
virtual bool delOption(const String& name, const String& item);
|
||||
virtual bool getText(const String& name, String& text);
|
||||
virtual bool getCheck(const String& name, bool& checked);
|
||||
virtual void populate();
|
||||
virtual void init();
|
||||
virtual void show();
|
||||
virtual void hide();
|
||||
virtual void size(int width, int height);
|
||||
virtual void move(int x, int y);
|
||||
virtual void moveRel(int dx, int dy);
|
||||
virtual void geometry(int x, int y, int w, int h);
|
||||
virtual GtkWidget* filler();
|
||||
virtual GtkWidget* container(Layout layout) const;
|
||||
virtual GtkWidget* container(const String& layout) const;
|
||||
virtual GtkWidget* build(const String& type, const String& text);
|
||||
GtkWidget* find(const String& name) const;
|
||||
virtual void insert(GtkWidget* wid, int x = 0, int y = 0, int w = -1, int h = -1);
|
||||
virtual bool action(GtkWidget* wid);
|
||||
virtual bool toggle(GtkToggleButton* btn, gboolean active);
|
||||
virtual bool select(GtkOptionMenu* opt, gint selected);
|
||||
virtual void menu(int x, int y);
|
||||
inline GtkWidget* widget() const
|
||||
{ return m_widget; }
|
||||
inline int state() const
|
||||
{ return m_state; }
|
||||
inline void state(int gdkState)
|
||||
{ m_state = gdkState; }
|
||||
bool prepare();
|
||||
bool restore();
|
||||
static bool setText(GtkWidget* wid, const String& text);
|
||||
static bool setCheck(GtkWidget* wid, bool checked);
|
||||
static bool setSelect(GtkWidget* wid, const String& item);
|
||||
static bool addOption(GtkWidget* wid, const String& item, bool atStart = false);
|
||||
static bool delOption(GtkWidget* wid, const String& item);
|
||||
static bool getText(GtkWidget* wid, String& text);
|
||||
static bool getCheck(GtkWidget* wid, bool& checked);
|
||||
protected:
|
||||
GtkWidget* m_widget;
|
||||
GtkWidget* m_filler;
|
||||
int m_layout;
|
||||
int m_state;
|
||||
gint m_posX;
|
||||
gint m_posY;
|
||||
gint m_sizeW;
|
||||
gint m_sizeH;
|
||||
};
|
||||
|
||||
/**
|
||||
* Each instance of WindowFactory creates special windows by name
|
||||
* @short A static window creator
|
||||
*/
|
||||
class YGTK2_API WindowFactory : public UIFactory
|
||||
{
|
||||
YCLASS(WindowFactory,UIFactory)
|
||||
public:
|
||||
WindowFactory(const char* type, const char* name);
|
||||
virtual Window* build() const = 0;
|
||||
};
|
||||
|
||||
#define WINDOW_FACTORY(type,name,cls) \
|
||||
class cls##__Factory : public WindowFactory \
|
||||
{ public: cls##__Factory() : WindowFactory(type,name) {} \
|
||||
Window* build() const { return new cls(name); } }; \
|
||||
cls##__Factory cls##__FactoryInstance;
|
||||
|
||||
/**
|
||||
* Each instance of WidgetFactory creates special widgets by name
|
||||
* @short A static widget creator
|
||||
*/
|
||||
class YGTK2_API WidgetFactory : public UIFactory
|
||||
{
|
||||
YCLASS(WidgetFactory,UIFactory)
|
||||
public:
|
||||
WidgetFactory(const char* type, const char* name);
|
||||
virtual Widget* build(const String& text) const = 0;
|
||||
};
|
||||
|
||||
#define WIDGET_FACTORY(type,name,cls) \
|
||||
class cls##__Factory : public WidgetFactory \
|
||||
{ public: cls##__Factory() : WidgetFactory(type,name) {} \
|
||||
Widget* build(const String& text) const { return new cls(text); } }; \
|
||||
cls##__Factory cls##__FactoryInstance;
|
||||
|
||||
}; // namespace TelEngine
|
||||
|
||||
/* vi: set ts=8 sw=4 sts=4 noet: */
|
|
@ -0,0 +1,681 @@
|
|||
/**
|
||||
* 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"
|
||||
|
||||
using namespace TelEngine;
|
||||
|
||||
class UIHandler : public MessageHandler
|
||||
{
|
||||
public:
|
||||
UIHandler()
|
||||
: MessageHandler("ui.action",150)
|
||||
{ }
|
||||
virtual bool received(Message &msg);
|
||||
};
|
||||
|
||||
|
||||
Window::Window(const char* id)
|
||||
: m_id(id), m_visible(false), m_master(false)
|
||||
{
|
||||
}
|
||||
|
||||
Window::~Window()
|
||||
{
|
||||
if (Client::self())
|
||||
Client::self()->m_windows.remove(this,false);
|
||||
}
|
||||
|
||||
const String& Window::toString() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
bool Window::related(const Window* wnd) const
|
||||
{
|
||||
if ((wnd == this) || !wnd || wnd->master())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
Client* Client::s_client = 0;
|
||||
int Client::s_changing = 0;
|
||||
|
||||
Client::Client(const char *name)
|
||||
: Thread(name), m_line(0)
|
||||
{
|
||||
s_client = this;
|
||||
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();
|
||||
setStatus("");
|
||||
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);
|
||||
}
|
||||
|
||||
bool Client::setVisible(const String& name, bool show)
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
bool Client::setShow(const String& name, bool visible, Window* wnd, Window* skip)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
bool Client::addOption(const String& name, const String& item, bool atStart, Window* wnd, Window* skip)
|
||||
{
|
||||
if (wnd)
|
||||
return wnd->addOption(name,item,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->addOption(name,item,atStart) || ok;
|
||||
}
|
||||
--s_changing;
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool Client::delOption(const String& name, const String& item, Window* wnd, Window* skip)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
bool Client::getText(const String& name, String& text, Window* wnd, Window* skip)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
return getText(name,item,wnd,skip);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
lock();
|
||||
bool ok = setStatus(text,wnd);
|
||||
unlock();
|
||||
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);
|
||||
String line;
|
||||
getText("line",line,wnd);
|
||||
String proto;
|
||||
getText("proto",proto,wnd);
|
||||
return callStart(target,line,proto);
|
||||
}
|
||||
else if (name.startsWith("callto:"))
|
||||
return callStart(name.substr(7));
|
||||
else if (name == "accept") {
|
||||
callAccept(m_incoming);
|
||||
return true;
|
||||
}
|
||||
else if (name.startsWith("accept:")) {
|
||||
callAccept(name.substr(7));
|
||||
return true;
|
||||
}
|
||||
else if (name == "reject") {
|
||||
callReject(m_incoming);
|
||||
return true;
|
||||
}
|
||||
else if (name.startsWith("reject:")) {
|
||||
callReject(name.substr(7));
|
||||
return true;
|
||||
}
|
||||
else if (name == "hangup") {
|
||||
callHangup(m_incoming);
|
||||
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;
|
||||
}
|
||||
}
|
||||
Message* m = new Message("ui.event");
|
||||
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);
|
||||
if (setVisible(name,active))
|
||||
return true;
|
||||
setCheck(name,active,0,wnd);
|
||||
Message* m = new Message("ui.event");
|
||||
m->addParam("event","toggle");
|
||||
m->addParam("name",name);
|
||||
m->addParam("active",String::boolText(active));
|
||||
Engine::enqueue(m);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Client::select(Window* wnd, const String& name, const String& item)
|
||||
{
|
||||
DDebug(ClientDriver::self(),DebugInfo,"Select '%s' '%s' in %p",
|
||||
name.c_str(),item.c_str(),wnd);
|
||||
setSelect(name,item,0,wnd);
|
||||
Message* m = new Message("ui.event");
|
||||
m->addParam("event","select");
|
||||
m->addParam("name",name);
|
||||
m->addParam("item",item);
|
||||
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);
|
||||
ClientChannel* cc = static_cast<ClientChannel*>(ClientDriver::self()->find(callId));
|
||||
if (cc) {
|
||||
cc->openMedia();
|
||||
Engine::enqueue(cc->message("call.answered",false,true));
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
bool Client::callStart(const String& target, const String& line, const String& proto)
|
||||
{
|
||||
Debug(ClientDriver::self(),DebugInfo,"callStart('%s','%s','%s')",
|
||||
target.c_str(),line.c_str(),proto.c_str());
|
||||
if (target.null())
|
||||
return false;
|
||||
ClientChannel* cc = new ClientChannel();
|
||||
Message* m = cc->message("call.route");
|
||||
Regexp r("^[a-z]\\+/");
|
||||
if (r.matches(target.safe()))
|
||||
m->setParam("callto",target);
|
||||
else
|
||||
m->setParam("called",target);
|
||||
if (line)
|
||||
m->setParam("line",line);
|
||||
if (proto)
|
||||
m->setParam("protocol",proto);
|
||||
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);
|
||||
if (msg && msg->userData()) {
|
||||
CallEndpoint* ch = static_cast<CallEndpoint*>(msg->userData());
|
||||
ClientChannel* cc = new ClientChannel(ch->id());
|
||||
if (cc->connect(ch)) {
|
||||
m_incoming = cc->id();
|
||||
msg->setParam("peerid",m_incoming);
|
||||
msg->setParam("targetid",m_incoming);
|
||||
Engine::enqueue(cc->message("call.ringing",false,true));
|
||||
cc->deref();
|
||||
// notify the UI about the call
|
||||
String tmp("Call from:");
|
||||
tmp << " " << caller;
|
||||
lock();
|
||||
setStatus(tmp);
|
||||
setText("incoming",tmp);
|
||||
setVisible("incoming");
|
||||
unlock();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Client::clearIncoming(const String& id)
|
||||
{
|
||||
if (id == m_incoming)
|
||||
m_incoming.clear();
|
||||
}
|
||||
|
||||
bool UIHandler::received(Message &msg)
|
||||
{
|
||||
if (!Client::self())
|
||||
return false;
|
||||
String action(msg.getValue("action"));
|
||||
if (action.null())
|
||||
return false;
|
||||
Window* wnd = Client::getWindow(msg.getValue("window"));
|
||||
if (action == "set_status")
|
||||
return Client::self()->setStatusLocked(msg.getValue("status"),wnd);
|
||||
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;
|
||||
Client::self()->lock();
|
||||
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);
|
||||
else if (action == "add_option")
|
||||
ok = Client::self()->addOption(name,msg.getValue("item"),msg.getBoolValue("insert"),wnd);
|
||||
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);
|
||||
Client::self()->unlock();
|
||||
return ok;
|
||||
}
|
||||
|
||||
// IMPORTANT: having a target means "from inside Yate to the user"
|
||||
// An user initiated call must be incoming (no target)
|
||||
ClientChannel::ClientChannel(const char* target)
|
||||
: Channel(ClientDriver::self(),0,target), m_line(0)
|
||||
{
|
||||
m_targetid = target;
|
||||
Engine::enqueue(message("chan.startup"));
|
||||
}
|
||||
|
||||
ClientChannel::~ClientChannel()
|
||||
{
|
||||
closeMedia();
|
||||
String tmp("Hung up:");
|
||||
tmp << " " << (address() ? address() : id());
|
||||
if (Client::self()) {
|
||||
Client::self()->clearIncoming(id());
|
||||
Client::self()->setStatusLocked(tmp);
|
||||
}
|
||||
Engine::enqueue(message("chan.hangup"));
|
||||
}
|
||||
|
||||
bool ClientChannel::openMedia()
|
||||
{
|
||||
String dev = ClientDriver::device();
|
||||
if (dev.null())
|
||||
return false;
|
||||
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;
|
||||
}
|
||||
|
||||
bool ClientChannel::callRouted(Message& msg)
|
||||
{
|
||||
String tmp("Calling:");
|
||||
tmp << " " << msg.retValue();
|
||||
Client::self()->setStatusLocked(tmp);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ClientChannel::callAccept(Message& msg)
|
||||
{
|
||||
Debug(ClientDriver::self(),DebugAll,"ClientChannel::callAccept() [%p]",this);
|
||||
Client::self()->setStatusLocked("Call connected");
|
||||
Channel::callAccept(msg);
|
||||
}
|
||||
|
||||
void ClientChannel::callReject(const char* error, const char* reason)
|
||||
{
|
||||
Debug(ClientDriver::self(),DebugAll,"ClientChannel::callReject('%s','%s') [%p]",
|
||||
error,reason,this);
|
||||
if (!reason)
|
||||
reason = error;
|
||||
if (!reason)
|
||||
reason = "Unknown reason";
|
||||
String tmp("Call failed:");
|
||||
tmp << " " << reason;
|
||||
if (Client::self())
|
||||
Client::self()->setStatusLocked(tmp);
|
||||
Channel::callReject(error,reason);
|
||||
}
|
||||
|
||||
bool ClientChannel::msgRinging(Message& msg)
|
||||
{
|
||||
Debug(ClientDriver::self(),DebugAll,"ClientChannel::msgRinging() [%p]",this);
|
||||
Client::self()->setStatusLocked("Call ringing");
|
||||
return Channel::msgRinging(msg);
|
||||
}
|
||||
|
||||
bool ClientChannel::msgAnswered(Message& msg)
|
||||
{
|
||||
Debug(ClientDriver::self(),DebugAll,"ClientChannel::msgAnswered() [%p]",this);
|
||||
Client::self()->setStatusLocked("Call answered");
|
||||
openMedia();
|
||||
return Channel::msgAnswered(msg);
|
||||
}
|
||||
|
||||
|
||||
ClientDriver* ClientDriver::s_driver = 0;
|
||||
String ClientDriver::s_device;
|
||||
|
||||
ClientDriver::ClientDriver()
|
||||
: Driver("client","misc")
|
||||
{
|
||||
s_driver = this;
|
||||
}
|
||||
|
||||
ClientDriver::~ClientDriver()
|
||||
{
|
||||
s_driver = 0;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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: */
|
|
@ -18,14 +18,16 @@ MKDEPS := ../config.status
|
|||
YLIB:= libyate.so.@PACKAGE_VERSION@
|
||||
CINC := @top_srcdir@/yateclass.h
|
||||
EINC := $(CINC) @top_srcdir@/yatengine.h
|
||||
PINC := $(PINC) @top_srcdir@/yatephone.h
|
||||
PINC := $(EINC) @top_srcdir@/yatephone.h
|
||||
CLINC:= $(PINC) @top_srcdir@/yatecbase.h
|
||||
LIBS :=
|
||||
CLSOBJS := TelEngine.o ObjList.o String.o DataBlock.o NamedList.o YMD5.o \
|
||||
Mutex.o Thread.o Socket.o
|
||||
ENGOBJS := Configuration.o Message.o Plugin.o Engine.o
|
||||
TELOBJS := DataFormat.o Channel.o
|
||||
CLIOBJS := Client.o
|
||||
|
||||
LIBOBJS := $(CLSOBJS) $(ENGOBJS) $(TELOBJS)
|
||||
LIBOBJS := $(CLSOBJS) $(ENGOBJS) $(TELOBJS) $(CLIOBJS)
|
||||
CLEANS = $(LIBOBJS) core
|
||||
COMPILE = $(CXX) $(DEFS) $(DEBUG) $(INCLUDES) $(CFLAGS)
|
||||
LINK = $(CXX) $(LDFLAGS)
|
||||
|
@ -68,6 +70,9 @@ Mutex.o: @srcdir@/Mutex.cpp $(MKDEPS) $(CINC)
|
|||
Thread.o: @srcdir@/Thread.cpp $(MKDEPS) $(CINC)
|
||||
$(COMPILE) @THREAD_KILL@ -c $<
|
||||
|
||||
Client.o: @srcdir@/Client.cpp $(MKDEPS) $(CLINC)
|
||||
$(COMPILE) -c $<
|
||||
|
||||
%.o: @srcdir@/%.cpp $(MKDEPS) $(EINC)
|
||||
$(COMPILE) -c $<
|
||||
|
||||
|
|
|
@ -120,6 +120,12 @@ GenObject* ObjList::operator[](int index) const
|
|||
return obj ? obj->get() : 0;
|
||||
}
|
||||
|
||||
GenObject* ObjList::operator[](const String& str) const
|
||||
{
|
||||
ObjList *obj = find(str);
|
||||
return obj ? obj->get() : 0;
|
||||
}
|
||||
|
||||
ObjList* ObjList::find(const GenObject* obj) const
|
||||
{
|
||||
XDebug(DebugAll,"ObjList::find(%p) [%p]",obj,this);
|
||||
|
|
|
@ -17,7 +17,7 @@ MODFLAGS:= @MODULE_LDFLAGS@
|
|||
MODSTRIP:= @MODULE_SYMBOLS@
|
||||
INCFILES := @top_srcdir@/yatengine.h @top_srcdir@/yatephone.h ../yateversn.h
|
||||
|
||||
SUBDIRS :=
|
||||
SUBDIRS := gtk2
|
||||
MKDEPS := ../config.status
|
||||
PROGS := cdrbuild.yate cdrfile.yate \
|
||||
regexroute.yate regfile.yate accfile.yate \
|
||||
|
@ -55,6 +55,10 @@ ifneq (@HAVE_GSM@,no)
|
|||
PROGS := $(PROGS) gsmcodec.yate
|
||||
endif
|
||||
|
||||
ifeq (@HAVE_GTK2@_@HAVE_GMOZ@,yes_yes)
|
||||
PROGS := $(PROGS) gtk2/gtk2mozilla.yate
|
||||
endif
|
||||
|
||||
LOCALFLAGS =
|
||||
LOCALLIBS =
|
||||
COMPILE = $(CXX) $(DEFS) $(DEBUG) $(INCLUDES) $(CFLAGS)
|
||||
|
@ -80,14 +84,21 @@ clean: do-clean
|
|||
.PHONY: install
|
||||
install: all do-install
|
||||
@mkdir -p "$(DESTDIR)$(moddir)/" && \
|
||||
install $(PROGS) "$(DESTDIR)$(moddir)/"
|
||||
for i in $(PROGS) ; do \
|
||||
install -D "$$i" "$(DESTDIR)$(moddir)/$$i" ; \
|
||||
done;
|
||||
|
||||
.PHONY: uninstall
|
||||
uninstall: do-uninstall
|
||||
@-for i in $(PROGS) ; do \
|
||||
rm "$(DESTDIR)$(moddir)/$$i" ; \
|
||||
done; \
|
||||
rmdir "$(DESTDIR)$(moddir)"
|
||||
$(if $(SUBDIRS),\
|
||||
for i in $(SUBDIRS) ; do \
|
||||
rmdir "$(DESTDIR)$(moddir)/$$i" ; \
|
||||
done; \
|
||||
)
|
||||
@-rmdir "$(DESTDIR)$(moddir)"
|
||||
|
||||
%.o: @srcdir@/%.cpp $(MKDEPS) $(INCFILES)
|
||||
$(COMPILE) -c $<
|
||||
|
@ -142,6 +153,10 @@ yrtpchan.yate: ../contrib/yrtp/libyatertp.a
|
|||
yrtpchan.yate: LOCALFLAGS = -I@top_srcdir@/contrib/yrtp
|
||||
yrtpchan.yate: LOCALLIBS = ../contrib/yrtp/libyatertp.a
|
||||
|
||||
gtk2/gtk2mozilla.yate: @top_srcdir@/contrib/gtk2/gtk2client.h
|
||||
gtk2/gtk2mozilla.yate: LOCALFLAGS = @GTK2_INC@ @GMOZ_INC@ -I@top_srcdir@/contrib/gtk2
|
||||
gtk2/gtk2mozilla.yate: LOCALLIBS = @GMOZ_LIB@
|
||||
|
||||
../contrib/iax/libiax.a:
|
||||
$(MAKE) -C ../contrib/iax
|
||||
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
Makefile
|
||||
core*
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
*.yate
|
||||
*.orig
|
||||
*~
|
||||
.*.swp
|
|
@ -0,0 +1,101 @@
|
|||
/**
|
||||
* gtk2mozilla.cpp
|
||||
* This file is part of the YATE Project http://YATE.null.ro
|
||||
*
|
||||
* Mozilla embedded widget for the Gtk2 based universal telephony client
|
||||
*
|
||||
* 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 "gtk2client.h"
|
||||
#include <gtkmozembed.h>
|
||||
|
||||
using namespace TelEngine;
|
||||
|
||||
// Embedded Mozilla widget
|
||||
class MozWidget : public Widget
|
||||
{
|
||||
public:
|
||||
MozWidget(const String& text);
|
||||
virtual ~MozWidget();
|
||||
virtual bool setText(const String& text);
|
||||
virtual bool getText(String& text);
|
||||
void setTextAsync();
|
||||
protected:
|
||||
String m_url;
|
||||
};
|
||||
|
||||
WIDGET_FACTORY("gtk2","mozilla",MozWidget)
|
||||
|
||||
static Mutex s_mutex;
|
||||
|
||||
static gboolean mozIntervalCb(gpointer dat)
|
||||
{
|
||||
if (dat)
|
||||
static_cast<MozWidget*>(dat)->setTextAsync();
|
||||
return false;
|
||||
}
|
||||
|
||||
MozWidget::MozWidget(const String& text)
|
||||
{
|
||||
DDebug(ClientDriver::self(),DebugAll,"MozWidget::MozWidget()");
|
||||
widget(gtk_moz_embed_new());
|
||||
setText(text);
|
||||
}
|
||||
|
||||
MozWidget::~MozWidget()
|
||||
{
|
||||
DDebug(ClientDriver::self(),DebugAll,"MozWidget::~MozWidget()");
|
||||
}
|
||||
|
||||
bool MozWidget::setText(const String& text)
|
||||
{
|
||||
if (widget() && text) {
|
||||
s_mutex.lock();
|
||||
m_url = text;
|
||||
gtk_timeout_add(1,mozIntervalCb,this);
|
||||
s_mutex.unlock();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MozWidget::getText(String& text)
|
||||
{
|
||||
if (widget()) {
|
||||
char* url = gtk_moz_embed_get_location(GTK_MOZ_EMBED(widget()));
|
||||
text = url;
|
||||
delete url;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void MozWidget::setTextAsync()
|
||||
{
|
||||
s_mutex.lock();
|
||||
if (widget() && m_url) {
|
||||
Debug(ClientDriver::self(),DebugAll,"MozWidget async url='%s'",m_url.c_str());
|
||||
gtk_moz_embed_load_url(GTK_MOZ_EMBED(widget()),m_url.c_str());
|
||||
m_url.clear();
|
||||
}
|
||||
s_mutex.unlock();
|
||||
}
|
||||
|
||||
/* vi: set ts=8 sw=4 sts=4 noet: */
|
|
@ -0,0 +1,37 @@
|
|||
pixmap_path "/usr/src/yate09-gtk2/clients"
|
||||
|
||||
style "tux" {
|
||||
bg_pixmap[NORMAL] = "tux.xpm"
|
||||
}
|
||||
|
||||
style "brown" {
|
||||
bg[NORMAL] = { 0.80, 0.75, 0.25 }
|
||||
}
|
||||
|
||||
style "red" {
|
||||
bg[NORMAL] = { 1.0, 0.5, 0.5 }
|
||||
}
|
||||
|
||||
style "green" {
|
||||
bg[NORMAL] = { 0.5, 1.0, 0.5 }
|
||||
}
|
||||
|
||||
style "blue" {
|
||||
bg[NORMAL] = { 0.5, 0.5, 1.0 }
|
||||
GtkButton::default_border = { 5, 0, 5, 0 }
|
||||
}
|
||||
|
||||
style "sky" {
|
||||
bg[NORMAL] = { 0.85, 0.85, 1.0 }
|
||||
}
|
||||
|
||||
widget_class "default" style "tux"
|
||||
#class "GtkWindow" style "brown"
|
||||
#widget "default" style "brown"
|
||||
widget "browser" style "sky"
|
||||
widget "*.call" style "green"
|
||||
widget "*.accept" style "green"
|
||||
widget "*.reject" style "red"
|
||||
widget "*.hangup" style "red"
|
||||
widget "*.caption" style "sky"
|
||||
widget "*.decoration" style "blue"
|
|
@ -0,0 +1,72 @@
|
|||
[default]
|
||||
enabled=on
|
||||
title=Yate VoIP Client
|
||||
master=yes
|
||||
layout=fixed
|
||||
width=220
|
||||
height=130
|
||||
label=10,5,100,20,Yate
|
||||
label=10,30,150,20,Call address or number
|
||||
combo=10,50,150,22,callto,
|
||||
label=170,30,40,20,Line
|
||||
option=170,48,40,30,line,l 1,l 2,l 3
|
||||
button=10,80,100,28,call,Call
|
||||
button=110,80,100,28,hangup,Hangup
|
||||
label=10,110,200,20,status,Initializing...
|
||||
check=75,5,20,20,ctest,Test
|
||||
toggle=135,5,20,20,browser,
|
||||
toggle=155,5,20,20,tools,
|
||||
button_icon=175,5,20,20,decoration,
|
||||
button_hide=195,5,20,20,decoration,
|
||||
x=489
|
||||
y=368
|
||||
[tools]
|
||||
enabled=off
|
||||
title=Tools
|
||||
label=Tools Window
|
||||
check=160,5,20,20,ctest,Test
|
||||
button_hide=0,0,20,20,decoration,
|
||||
x=608
|
||||
y=314
|
||||
[browser]
|
||||
enabled=on
|
||||
title=Browser
|
||||
master=yes
|
||||
layout=framed
|
||||
vbox=>
|
||||
hbox=,,0,-1
|
||||
label=1,1,,,Browser window
|
||||
button_icon=,,20,20,decoration,
|
||||
button_max=,,20,20,decoration,
|
||||
button_hide=,,20,20,decoration,
|
||||
leave=<
|
||||
mozilla=1,1,300,400,browser,file:///usr/share/gtk-doc/html/gtk/GtkWidget.html#gtk-widget-set-size-request
|
||||
editor=,1,200,22,callto,
|
||||
hbox=,,0,-1
|
||||
button=1,,100,30,call,Call
|
||||
button=1,,100,30,hangup,Hangup
|
||||
button=1,,100,30,mumu,Mumu
|
||||
leave=<
|
||||
label=,,,,status,Initializing...
|
||||
leave=<
|
||||
x=688
|
||||
y=40
|
||||
[incoming]
|
||||
enabled=on
|
||||
title=Incoming Call
|
||||
layout=framed
|
||||
vbox=>
|
||||
boxed=0,0,-1,-1,caption,>
|
||||
hbox=,,0,-1
|
||||
label=1,1,,,Incoming call
|
||||
button_hide=,,20,20,decoration,
|
||||
leave=<
|
||||
leave=<
|
||||
label=,,,,incoming,No call
|
||||
hbox=
|
||||
button=1,,75,30,accept,Accept
|
||||
button=1,,75,30,reject,Reject
|
||||
leave=<
|
||||
leave=<
|
||||
x=688
|
||||
y=536
|
|
@ -0,0 +1,202 @@
|
|||
/**
|
||||
* yatecbase.h
|
||||
* This file is part of the YATE Project http://YATE.null.ro
|
||||
*
|
||||
* Common base classes for all telephony clients
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __YATECBASE_H
|
||||
#define __YATECBASE_H
|
||||
|
||||
#ifndef __cplusplus
|
||||
#error C++ is required
|
||||
#endif
|
||||
|
||||
#include <yatephone.h>
|
||||
|
||||
/**
|
||||
* Holds all Telephony Engine related classes.
|
||||
*/
|
||||
namespace TelEngine {
|
||||
|
||||
/**
|
||||
* A window is the basic user interface element.
|
||||
* Everything inside is implementation specific functionality.
|
||||
* @short An abstract user interface window
|
||||
*/
|
||||
class YATE_API Window : public GenObject
|
||||
{
|
||||
friend class Client;
|
||||
public:
|
||||
Window(const char* id = 0);
|
||||
virtual ~Window();
|
||||
virtual const String& toString() const;
|
||||
virtual bool setActive(const String& name, bool active) = 0;
|
||||
virtual bool setShow(const String& name, bool visible) = 0;
|
||||
virtual bool setText(const String& name, const String& text) = 0;
|
||||
virtual bool setCheck(const String& name, bool checked) = 0;
|
||||
virtual bool setSelect(const String& name, const String& item) = 0;
|
||||
virtual bool addOption(const String& name, const String& item, bool atStart = false) = 0;
|
||||
virtual bool delOption(const String& name, const String& item) = 0;
|
||||
virtual bool getText(const String& name, String& text) = 0;
|
||||
virtual bool getCheck(const String& name, bool& checked) = 0;
|
||||
virtual void populate() = 0;
|
||||
virtual void init() = 0;
|
||||
virtual void show() = 0;
|
||||
virtual void hide() = 0;
|
||||
virtual void size(int width, int height) = 0;
|
||||
virtual void move(int x, int y) = 0;
|
||||
virtual void moveRel(int dx, int dy) = 0;
|
||||
virtual bool related(const Window* wnd) const;
|
||||
virtual void menu(int x, int y) = 0;
|
||||
inline const String& id() const
|
||||
{ return m_id; }
|
||||
inline bool visible() const
|
||||
{ return m_visible; }
|
||||
inline void visible(bool yes)
|
||||
{ if (yes) show(); else hide(); }
|
||||
inline bool master() const
|
||||
{ return m_master; }
|
||||
protected:
|
||||
String m_id;
|
||||
bool m_visible;
|
||||
bool m_master;
|
||||
};
|
||||
|
||||
/**
|
||||
* Each instance of UIFactory creates special user interface elements by name
|
||||
* @short A static user interface creator
|
||||
*/
|
||||
class YATE_API UIFactory : public String
|
||||
{
|
||||
public:
|
||||
UIFactory(const char* type, const char* name);
|
||||
virtual ~UIFactory();
|
||||
};
|
||||
|
||||
/**
|
||||
* Singleton class that holds the User Interface's main thread and methods
|
||||
* @short Thread that runs the User Interface
|
||||
*/
|
||||
class YATE_API Client : public Thread
|
||||
{
|
||||
friend class Window;
|
||||
public:
|
||||
Client(const char *name = 0);
|
||||
virtual ~Client();
|
||||
virtual void run();
|
||||
virtual void main() = 0;
|
||||
virtual void lock() = 0;
|
||||
virtual void unlock() = 0;
|
||||
virtual void allHidden() = 0;
|
||||
virtual bool createWindow(const String& name) = 0;
|
||||
virtual bool setStatus(const String& text, Window* wnd = 0);
|
||||
bool setStatusLocked(const String& text, Window* wnd = 0);
|
||||
virtual bool action(Window* wnd, const String& name);
|
||||
virtual bool toggle(Window* wnd, const String& name, bool active);
|
||||
virtual bool select(Window* wnd, const String& name, const String& item);
|
||||
virtual bool callIncoming(const String& caller, const String& dest = String::empty(), Message* msg = 0);
|
||||
void clearIncoming(const String& id);
|
||||
void callAccept(const char* callId = 0);
|
||||
void callReject(const char* callId = 0);
|
||||
void callHangup(const char* callId = 0);
|
||||
bool callStart(const String& target, const String& line = String::empty(), const String& proto = String::empty());
|
||||
bool emitDigit(char digit);
|
||||
inline int line() const
|
||||
{ return m_line; }
|
||||
void line(int newLine);
|
||||
bool setActive(const String& name, bool active, Window* wnd = 0, Window* skip = 0);
|
||||
bool setShow(const String& name, bool visible, Window* wnd = 0, Window* skip = 0);
|
||||
bool setText(const String& name, const String& text, Window* wnd = 0, Window* skip = 0);
|
||||
bool setCheck(const String& name, bool checked, Window* wnd = 0, Window* skip = 0);
|
||||
bool setSelect(const String& name, const String& item, Window* wnd = 0, Window* skip = 0);
|
||||
bool addOption(const String& name, const String& item, bool atStart, Window* wnd = 0, Window* skip = 0);
|
||||
bool delOption(const String& name, const String& item, Window* wnd = 0, Window* skip = 0);
|
||||
bool getText(const String& name, String& text, Window* wnd = 0, Window* skip = 0);
|
||||
bool getCheck(const String& name, bool& checked, Window* wnd = 0, Window* skip = 0);
|
||||
bool getSelect(const String& name, String& item, Window* wnd = 0, Window* skip = 0);
|
||||
void moveRelated(const Window* wnd, int dx, int dy);
|
||||
inline static Client* self()
|
||||
{ return s_client; }
|
||||
inline static bool changing()
|
||||
{ return (s_changing > 0); }
|
||||
static Window* getWindow(const String& name);
|
||||
static bool setVisible(const String& name, bool show = true);
|
||||
static bool getVisible(const String& name);
|
||||
protected:
|
||||
virtual void loadWindows() = 0;
|
||||
virtual void initWindows();
|
||||
ObjList m_windows;
|
||||
String m_incoming;
|
||||
int m_line;
|
||||
static Client* s_client;
|
||||
static int s_changing;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements a Channel used by client programs
|
||||
* @short Channel used by client programs
|
||||
*/
|
||||
class YATE_API ClientChannel : public Channel
|
||||
{
|
||||
public:
|
||||
ClientChannel(const char* target = 0);
|
||||
virtual ~ClientChannel();
|
||||
virtual bool msgRinging(Message& msg);
|
||||
virtual bool msgAnswered(Message& msg);
|
||||
virtual bool callRouted(Message& msg);
|
||||
virtual void callAccept(Message& msg);
|
||||
virtual void callReject(const char* error, const char* reason);
|
||||
bool openMedia();
|
||||
void closeMedia();
|
||||
inline int line() const
|
||||
{ return m_line; }
|
||||
void line(int newLine);
|
||||
protected:
|
||||
int m_line;
|
||||
};
|
||||
|
||||
/**
|
||||
* Abstract client Driver that implements some of the specific functionality
|
||||
* @short Base Driver with client specific functions
|
||||
*/
|
||||
class YATE_API ClientDriver : public Driver
|
||||
{
|
||||
public:
|
||||
ClientDriver();
|
||||
virtual ~ClientDriver();
|
||||
virtual void initialize() = 0;
|
||||
virtual bool factory(UIFactory* factory, const char* type);
|
||||
virtual bool msgExecute(Message& msg, String& dest);
|
||||
ClientChannel* findLine(int line);
|
||||
inline static ClientDriver* self()
|
||||
{ return s_driver; }
|
||||
inline static const String& device()
|
||||
{ return s_device; }
|
||||
protected:
|
||||
static ClientDriver* s_driver;
|
||||
static String s_device;
|
||||
};
|
||||
|
||||
}; // namespace TelEngine
|
||||
|
||||
#endif /* __YATECBASE_H */
|
||||
|
||||
/* vi: set ts=8 sw=4 sts=4 noet: */
|
|
@ -779,6 +779,13 @@ public:
|
|||
*/
|
||||
GenObject* operator[](int index) const;
|
||||
|
||||
/**
|
||||
* Array-like indexing operator
|
||||
* @param str String value of the object to locate
|
||||
* @return Pointer to the object or NULL
|
||||
*/
|
||||
GenObject* operator[](const String& str) const;
|
||||
|
||||
/**
|
||||
* Get the item in the list that holds an object
|
||||
* @param obj Pointer to the object to search for
|
||||
|
|
Loading…
Reference in New Issue