Commit c62f6835 authored by Margaux Clerc's avatar Margaux Clerc

add message storage

parent 26c4fe4f
......@@ -669,6 +669,24 @@ if test x$enable_tunnel = xtrue; then
AC_SUBST(TUNNEL_LIBS)
fi
AC_ARG_ENABLE(msg-storage,
[AS_HELP_STRING([--enable-msg-storage=[yes/no]], [Turn on compilation of message storage (default=yes)])],
[case "${enableval}" in
yes) enable_msg_storage=true ;;
no) enable_msg_storage=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-msg-storage) ;;
esac],
[enable_msg_storage=true]
)
AM_CONDITIONAL(BUILD_MSG_STORAGE, test x$enable_msg_storage = xtrue)
if test x$enable_msg_storage = xtrue; then
PKG_CHECK_MODULES(SQLITE3,[ sqlite3 >= 3.7.0],[],[
AC_MSG_ERROR([sqlite3 required for message storage not found.])] )
SQLITE3_CFLAGS+="-DMSG_STORAGE_ENABLED"
AC_SUBST(SQLITE3_CFLAGS)
AC_SUBST(SQLITE3_LIBS)
fi
dnl check for db2html (docbook) to generate html user manual
AC_CHECK_PROG(have_sgmltools, sgmltools, yes, no)
......@@ -781,6 +799,7 @@ printf "* %-30s %s\n" "GTK interface" $gtk_ui
printf "* %-30s %s\n" "Account assistant" $build_wizard
printf "* %-30s %s\n" "Console interface" $console_ui
printf "* %-30s %s\n" "Tools" $build_tools
printf "* %-30s %s\n" "Message storage" $enable_msg_storage
printf "* %-30s %s\n" "zRTP encryption (GPLv3)" $zrtp
printf "* %-30s %s\n" "uPnP support" $build_upnp
......
......@@ -14,6 +14,7 @@ COMMON_CFLAGS=\
$(READLINE_CFLAGS) \
$(OSIP_CFLAGS) \
$(ORTP_CFLAGS) \
$(SQLITE3_CFLAGS) \
$(MEDIASTREAMER_CFLAGS)
if BUILD_CONSOLE
......@@ -28,6 +29,7 @@ linphonec_SOURCES=linphonec.c linphonec.h commands.c
linphonec_CFLAGS=$(COMMON_CFLAGS) $(CONSOLE_FLAGS)
linphonec_LDADD=$(top_builddir)/coreapi/liblinphone.la \
$(READLINE_LIBS) \
$(SQLITE3_LIBS) \
$(X11_LIBS)
if BUILD_WIN32
......
......@@ -47,6 +47,7 @@ liblinphone_la_SOURCES=\
lsd.c linphonecore_utils.h \
ec-calibrator.c \
conference.c \
message_storage.c \
$(GITVERSION_FILE)
if BUILD_UPNP
......@@ -73,7 +74,9 @@ liblinphone_la_LIBADD= \
$(MEDIASTREAMER_LIBS) \
$(ORTP_LIBS) $(OPENSSL_LIBS) \
$(TUNNEL_LIBS) \
$(LIBSOUP_LIBS)
$(LIBSOUP_LIBS) \
$(SQLITE3_LIBS)
if BUILD_TESTS
noinst_PROGRAMS=test_lsd test_ecc test_numbers
......@@ -106,7 +109,8 @@ AM_CFLAGS=\
$(IPV6_CFLAGS) \
-DORTP_INET6 \
$(VIDEO_CFLAGS) \
$(TUNNEL_CFLAGS)
$(TUNNEL_CFLAGS) \
$(SQLITE3_CFLAGS)
if BUILD_WIZARD
AM_CFLAGS+= -DBUILD_WIZARD
......
......@@ -934,6 +934,7 @@ static void text_delivery_update(SalOp *op, SalTextDeliveryStatus status){
LinphoneChatMessage *chat_msg=(LinphoneChatMessage* )sal_op_get_user_pointer(op);
const MSList* calls = linphone_core_get_calls(chat_msg->chat_room->lc);
linphone_core_set_message_state(chat_msg->chat_room,chat_msg->message,chatStatusSal2Linphone(status),chat_msg->time);
if (chat_msg && chat_msg->cb) {
chat_msg->cb(chat_msg
,chatStatusSal2Linphone(status)
......
......@@ -62,12 +62,26 @@ void linphone_chat_room_destroy(LinphoneChatRoom *cr){
ms_free(cr->peer);
}
#ifdef WIN32
static inline char *my_ctime_r(const time_t *t, char *buf){
strcpy(buf,ctime(t));
return buf;
}
#else
#define my_ctime_r ctime_r
#endif
static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage* msg){
const char *route=NULL;
const char *identity=linphone_core_find_best_identity(cr->lc,cr->peer_url,&route);
SalOp *op=NULL;
LinphoneCall *call;
char* content_type;
time_t t=time(NULL);
char buf[26];
char *to;
if (lp_config_get_int(cr->lc->config,"sip","chat_use_call_dialogs",0)){
if((call = linphone_core_get_call_by_remote_address(cr->lc,cr->peer))!=NULL){
......@@ -82,6 +96,7 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM
}
}
}
msg->time=t;
if (op==NULL){
/*sending out of calls*/
op = sal_op_new(cr->lc->sal);
......@@ -94,11 +109,15 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM
}
if (msg->external_body_url) {
content_type=ms_strdup_printf("message/external-body; access-type=URL; URL=\"%s\"",msg->external_body_url);
sal_message_send(op,identity,cr->peer,content_type, NULL);
sal_message_send(op,identity,cr->peer,content_type, NULL,my_ctime_r(&t,buf));
ms_free(content_type);
} else {
sal_text_send(op, identity, cr->peer,msg->message);
sal_text_send(op, identity, cr->peer,msg->message,my_ctime_r(&t,buf));
}
to=linphone_address_as_string_uri_only (cr->peer_url);
linphone_core_set_history_message(cr,identity,to,OUTGOING,msg->message,
my_ctime_r(&t,buf),READ,LinphoneChatMessageStateInProgress);
ms_free(to);
}
/**
......@@ -130,8 +149,11 @@ void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessag
LinphoneChatRoom *cr=NULL;
LinphoneAddress *addr;
char *cleanfrom;
const char *to;
char *from;
LinphoneChatMessage* msg;
const SalCustomHeader *ch;
char buf[26];
addr=linphone_address_new(sal_msg->from);
linphone_address_clean(addr);
......@@ -142,7 +164,9 @@ void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessag
}
cr=NULL;
}
to=linphone_core_get_identity(lc);
cleanfrom=linphone_address_as_string(addr);
from=linphone_address_as_string_uri_only(addr);
if (cr==NULL){
/* create a new chat room */
cr=linphone_core_create_chat_room(lc,cleanfrom);
......@@ -150,6 +174,7 @@ void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessag
msg = linphone_chat_room_create_message(cr, sal_msg->text);
linphone_chat_message_set_from(msg, cr->peer_url);
msg->time=sal_msg->time;
msg->state=LinphoneChatMessageStateDelivered;
ch=sal_op_get_custom_header(op);
if (ch) msg->custom_headers=sal_custom_header_clone(ch);
......@@ -158,7 +183,11 @@ void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessag
}
linphone_address_destroy(addr);
linphone_chat_room_message_received(cr,lc,msg);
linphone_core_set_history_message(cr,to,from,INCOMING,
msg->message,my_ctime_r(&msg->time,buf),NOT_READ,
LinphoneChatMessageStateDelivered);
ms_free(cleanfrom);
ms_free(from);
}
/**
......@@ -215,6 +244,7 @@ LinphoneChatMessage* linphone_chat_room_create_message(LinphoneChatRoom *cr, con
void linphone_chat_room_send_message2(LinphoneChatRoom *cr, LinphoneChatMessage* msg,LinphoneChatMessageStateChangeCb status_cb, void* ud) {
msg->cb=status_cb;
msg->cb_ud=ud;
msg->state=LinphoneChatMessageStateInProgress;
_linphone_chat_room_send_message(cr, msg);
}
......@@ -308,6 +338,15 @@ time_t linphone_chat_message_get_time(const LinphoneChatMessage* message) {
return message->time;
}
/**
* Get the state of the message
*@param message #LinphoneChatMessage obj
*@return #LinphoneChatMessageState
*/
LinphoneChatMessageState linphone_chat_message_get_state(const LinphoneChatMessage* message) {
return message->state;
}
/**
* Get text part of this message
* @return text or NULL if no text.
......@@ -347,6 +386,9 @@ LinphoneChatMessage* linphone_chat_message_clone(const LinphoneChatMessage* msg)
void* message_userdata;
char* external_body_url;
LinphoneAddress* from;
time_t time;
SalCustomHeader *custom_headers;
LinphoneChatMessageState state;
};*/
LinphoneChatMessage* new_message = linphone_chat_room_create_message(msg->chat_room,msg->message);
if (msg->external_body_url) new_message->external_body_url=ms_strdup(msg->external_body_url);
......@@ -354,6 +396,8 @@ LinphoneChatMessage* linphone_chat_message_clone(const LinphoneChatMessage* msg)
new_message->cb_ud=msg->cb_ud;
new_message->message_userdata=msg->message_userdata;
new_message->cb=msg->cb;
new_message->time=msg->time;
new_message->state=msg->state;
if (msg->from) new_message->from=linphone_address_clone(msg->from);
return new_message;
}
......
......@@ -1306,6 +1306,9 @@ static void linphone_core_init (LinphoneCore * lc, const LinphoneCoreVTable *vta
#ifdef TUNNEL_ENABLED
lc->tunnel=linphone_core_tunnel_new(lc);
if (lc->tunnel) linphone_tunnel_configure(lc->tunnel);
#endif
#ifdef MSG_STORAGE_ENABLED
lc->db=linphone_message_storage_init();
#endif
if (lc->vtable.display_status)
lc->vtable.display_status(lc,_("Ready"));
......
......@@ -673,6 +673,7 @@ LinphoneCore* linphone_chat_room_get_lc(LinphoneChatRoom *cr);
void linphone_chat_room_set_user_data(LinphoneChatRoom *cr, void * ud);
void * linphone_chat_room_get_user_data(LinphoneChatRoom *cr);
LinphoneChatMessageState linphone_chat_message_get_state(const LinphoneChatMessage* message);
const char* linphone_chat_message_state_to_string(const LinphoneChatMessageState state);
LinphoneChatMessage* linphone_chat_message_clone(const LinphoneChatMessage* message);
void linphone_chat_message_set_from(LinphoneChatMessage* message, const LinphoneAddress* from);
......@@ -1417,7 +1418,8 @@ int linphone_core_get_audio_dscp(const LinphoneCore *lc);
void linphone_core_set_video_dscp(LinphoneCore *lc, int dscp);
int linphone_core_get_video_dscp(const LinphoneCore *lc);
MSList *linphone_chat_room_get_history(const char *to,LinphoneChatRoom *cr,int nb_message);
void linphone_core_set_messages_flag_read(LinphoneChatRoom *cr,const char *from, int read);
#ifdef __cplusplus
}
......
/*
message_storage.c
Copyright (C) 2012 Belledonne Communications, Grenoble, France
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "private.h"
#include "linphonecore.h"
#ifdef WIN32
static inline char *my_ctime_r(const time_t *t, char *buf){
strcpy(buf,ctime(t));
return buf;
}
#else
#define my_ctime_r ctime_r
#endif
#ifdef MSG_STORAGE_ENABLED
#include "sqlite3.h"
static const char *days[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
static const char *months[]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
#define CONFIG_FILE ".linphone-history.db"
char *linphone_message_storage_get_config_file(const char *filename){
const int path_max=1024;
char *config_file=(char *)malloc(path_max*sizeof(char));
if (filename==NULL) filename=CONFIG_FILE;
/*try accessing a local file first if exists*/
if (access(CONFIG_FILE,F_OK)==0){
snprintf(config_file,path_max,"%s",filename);
}else{
#ifdef WIN32
const char *appdata=getenv("APPDATA");
if (appdata){
snprintf(config_file,path_max,"%s\\%s",appdata,LINPHONE_CONFIG_DIR);
CreateDirectory(config_file,NULL);
snprintf(config_file,path_max,"%s\\%s\\%s",appdata,LINPHONE_CONFIG_DIR,filename);
}
#else
const char *home=getenv("HOME");
if (home==NULL) home=".";
snprintf(config_file,path_max,"%s/%s",home,filename);
#endif
}
return config_file;
}
void create_chat_message(char **argv, void *data){
LinphoneChatRoom *cr = (LinphoneChatRoom *)data;
LinphoneChatMessage* new_message = linphone_chat_room_create_message(cr,argv[4]);
struct tm ret={0};
char tmp1[80]={0};
char tmp2[80]={0};
if(atoi(argv[3])==INCOMING){
linphone_chat_message_set_from(new_message,linphone_address_new(argv[2]));
} else {
linphone_chat_message_set_from(new_message,linphone_address_new(argv[1]));
}
if(argv[5]!=NULL){
int i,j;
sscanf(argv[5],"%3c %3c%d%d:%d:%d %d",tmp1,tmp2,&ret.tm_mday,
&ret.tm_hour,&ret.tm_min,&ret.tm_sec,&ret.tm_year);
ret.tm_year-=1900;
for(i=0;i<7;i++) {
if(strcmp(tmp1,days[i])==0) ret.tm_wday=i;
}
for(j=0;j<12;j++) {
if(strcmp(tmp2,months[j])==0) ret.tm_mon=j;
}
}
new_message->time=argv[5]!=NULL ? mktime(&ret) : time(NULL);
new_message->state=atoi(argv[7]);
cr->messages_hist=ms_list_prepend(cr->messages_hist,(void *)new_message);
}
static int callback(void *data, int argc, char **argv, char **colName){
create_chat_message(argv,data);
return 0;
}
void linphone_sql_request_message(sqlite3 *db,const char *stmt,void *data){
char* errmsg;
int ret;
ret=sqlite3_exec(db,stmt,callback,data,&errmsg);
if(ret != SQLITE_OK) {
printf("Error in creation: %s.\n", errmsg);
}
}
void linphone_sql_request(sqlite3* db,const char *stmt){
char* errmsg;
int ret;
ret=sqlite3_exec(db,stmt,0,0,&errmsg);
if(ret != SQLITE_OK) {
printf("Error in creation: %s.\n", errmsg);
}
}
void linphone_core_set_history_message(LinphoneChatRoom *cr,const char *local_contact,const char *remote_contact,
int direction, const char *message,const char *date, int read, int state){
LinphoneCore *lc=linphone_chat_room_get_lc(cr);
char *buf=sqlite3_mprintf("insert into history values(NULL,%Q,%Q,%i,%Q,%Q,%i,%i);",
local_contact,remote_contact,direction,message,date,read,state);
linphone_sql_request(lc->db,buf);
}
void linphone_core_set_message_state(LinphoneChatRoom *cr,const char *message, int state, time_t date){
LinphoneCore *lc=linphone_chat_room_get_lc(cr);
char time_str[26];
char *buf=sqlite3_mprintf("update history set status=%i where message = %Q and time = %Q;",
state,message,my_ctime_r(&date,time_str));
linphone_sql_request(lc->db,buf);
}
void linphone_core_set_messages_flag_read(LinphoneChatRoom *cr,const char *from, int read){
LinphoneCore *lc=linphone_chat_room_get_lc(cr);
char *buf=sqlite3_mprintf("update history set read=%i where remoteContact = %Q;",
read,from);
linphone_sql_request(lc->db,buf);
}
MSList *linphone_chat_room_get_history(const char *to,LinphoneChatRoom *cr,int nb_message){
LinphoneCore *lc=linphone_chat_room_get_lc(cr);
cr->messages_hist = NULL;
char *buf=sqlite3_mprintf("select * from history where remoteContact = %Q order by id DESC limit %i ;",to,nb_message);
linphone_sql_request_message(lc->db,buf,(void *)cr);
return cr->messages_hist;
}
void linphone_close_storage(sqlite3* db){
sqlite3_close(db);
}
void linphone_create_table(sqlite3* db){
char* errmsg;
int ret;
ret=sqlite3_exec(db,"CREATE TABLE if not exists history (id INTEGER PRIMARY KEY AUTOINCREMENT, localContact TEXT NOT NULL, remoteContact TEXT NOT NULL, direction INTEGER, message TEXT, time TEXT NOT NULL, read INTEGER, status INTEGER);",
0,0,&errmsg);
if(ret != SQLITE_OK) {
printf("Error in creation: %s.\n", errmsg);
}
}
sqlite3 * linphone_message_storage_init(){
int ret;
char *errmsg;
sqlite3 *db;
char *filename;
filename=linphone_message_storage_get_config_file(NULL);
ret=sqlite3_open(filename,&db);
if(ret != SQLITE_OK) {
printf("Error in the opening: %s.\n", errmsg);
sqlite3_close(db);
}
linphone_create_table(db);
return db;
}
#else
void linphone_core_set_history_message(LinphoneChatRoom *cr,const char *local_contact,const char *remote_contact,
int direction, const char *message,const char *date, int read, int state){
}
void linphone_core_set_message_state(LinphoneChatRoom *cr,const char *message, int state, time_t date){
}
void linphone_core_set_messages_flag_read(LinphoneChatRoom *cr,const char *from, int read){
}
MSList *linphone_chat_room_get_history(const char *to,LinphoneChatRoom *cr,int nb_message){
return NULL;
}
#endif
\ No newline at end of file
......@@ -44,6 +44,10 @@ extern "C" {
#include "upnp.h"
#endif //BUILD_UPNP
#ifdef MSG_STORAGE_ENABLED
#include "sqlite3.h"
#endif
#ifndef LIBLINPHONE_VERSION
#define LIBLINPHONE_VERSION LINPHONE_VERSION
#endif
......@@ -125,6 +129,7 @@ struct _LinphoneChatMessage {
LinphoneAddress* from;
time_t time;
SalCustomHeader *custom_headers;
LinphoneChatMessageState state;
};
typedef struct StunCandidate{
......@@ -392,6 +397,7 @@ struct _LinphoneChatRoom{
char *peer;
LinphoneAddress *peer_url;
void * user_data;
MSList *messages_hist;
};
......@@ -610,6 +616,9 @@ struct _LinphoneCore
LinphoneTunnel *tunnel;
char* device_id;
MSList *last_recv_msg_ids;
#ifdef MSG_STORAGE_ENABLED
sqlite3 *db;
#endif
#ifdef BUILD_UPNP
UpnpContext *upnp;
#endif //BUILD_UPNP
......@@ -691,6 +700,20 @@ void linphone_call_params_uninit(LinphoneCallParams *params);
int linphone_upnp_init(LinphoneCore *lc);
void linphone_upnp_destroy(LinphoneCore *lc);
#define OUTGOING 0
#define INCOMING 1
#define NOT_READ 0
#define READ 1
#ifdef MSG_STORAGE_ENABLED
sqlite3 * linphone_message_storage_init();
#endif
void linphone_core_set_history_message(LinphoneChatRoom *cr,const char *local_contact,const char *remote_contact,
int direction, const char *message,const char *date, int read, int state);
void linphone_core_set_message_state(LinphoneChatRoom *cr,const char *message, int state,time_t date);
#ifdef __cplusplus
}
#endif
......
......@@ -430,8 +430,8 @@ int sal_register_refresh(SalOp *op, int expires);
int sal_unregister(SalOp *h);
/*Messaging */
int sal_text_send(SalOp *op, const char *from, const char *to, const char *text);
int sal_message_send(SalOp *op, const char *from, const char *to, const char* content_type, const char *msg);
int sal_text_send(SalOp *op, const char *from, const char *to, const char *text, const char*t);
int sal_message_send(SalOp *op, const char *from, const char *to, const char* content_type, const char *msg, const char*t);
/*presence Subscribe/notify*/
int sal_subscribe_presence(SalOp *op, const char *from, const char *to);
......
......@@ -1800,7 +1800,6 @@ static void text_received(Sal *sal, eXosip_event_t *ev){
}
}else ms_warning("No date header in SIP MESSAGE, we don't know when it was sent.");
content_type= osip_message_get_content_type(ev->request);
if (!content_type) {
ms_error("Could not get message because no content type");
......@@ -1848,8 +1847,6 @@ static void text_received(Sal *sal, eXosip_event_t *ev){
osip_free(from);
}
static void other_request(Sal *sal, eXosip_event_t *ev){
ms_message("in other_request");
if (ev->request==NULL) return;
......
......@@ -81,21 +81,8 @@ void sal_remove_in_subscribe(Sal *sal, SalOp *op){
sal->in_subscribes=ms_list_remove(sal->in_subscribes,op);
}
#ifdef WIN32
static inline char *my_ctime_r(const time_t *t, char *buf){
strcpy(buf,ctime(t));
return buf;
}
#else
#define my_ctime_r ctime_r
#endif
int sal_message_send(SalOp *op, const char *from, const char *to, const char* content_type, const char *msg){
int sal_message_send(SalOp *op, const char *from, const char *to, const char* content_type, const char *msg, const char *t){
osip_message_t *sip=NULL;
time_t t=time(NULL);
char buf[26];
if(op->cid == -1)
{
......@@ -111,7 +98,7 @@ int sal_message_send(SalOp *op, const char *from, const char *to, const char* co
sal_op_get_from(op),sal_op_get_route(op));
if (sip!=NULL){
sal_exosip_add_custom_headers(sip,op->base.custom_headers);
osip_message_set_date(sip,my_ctime_r(&t,buf));
osip_message_set_date(sip,t);
osip_message_set_content_type(sip,content_type);
if (msg) osip_message_set_body(sip,msg,strlen(msg));
sal_add_other(op->base.root,op,sip);
......@@ -141,8 +128,8 @@ int sal_message_send(SalOp *op, const char *from, const char *to, const char* co
return 0;
}
int sal_text_send(SalOp *op, const char *from, const char *to, const char *msg) {
return sal_message_send(op,from,to,"text/plain",msg);
int sal_text_send(SalOp *op, const char *from, const char *to, const char *msg,const char *t) {
return sal_message_send(op,from,to,"text/plain",msg,t);
}
/*presence Subscribe/notify*/
int sal_subscribe_presence(SalOp *op, const char *from, const char *to){
......
......@@ -55,7 +55,7 @@ linphone_SOURCES+= \
endif
linphone_LDADD= $(top_builddir)/coreapi/liblinphone.la \
$(LIBGTK_LIBS) $(NOTIFY1_LIBS) $(NOTIFY4_LIBS) $(LIBGTKMAC_LIBS) $(INTLLIBS)
$(LIBGTK_LIBS) $(NOTIFY1_LIBS) $(NOTIFY4_LIBS) $(LIBGTKMAC_LIBS) $(INTLLIBS) $(SQLITE3_LIBS)
if BUILD_WIN32
......@@ -79,7 +79,8 @@ AM_CFLAGS= -DIN_LINPHONE -I$(top_srcdir)/coreapi/ \
$(MEDIASTREAMER_CFLAGS) \
$(ORTP_CFLAGS) \
$(STRICT_OPTIONS) $(LIBGTK_CFLAGS) $(LIBGTKMAC_CFLAGS) $(IPV6_CFLAGS) \
$(TUNNEL_CFLAGS)
$(TUNNEL_CFLAGS) \
$(SQLITE3_CFLAGS)
version_date.h: $(top_srcdir)/configure.ac
......
This diff is collapsed.
......@@ -1556,10 +1556,6 @@ static void linphone_gtk_configure_main_window(){
static gboolean buttons_have_borders;
static gboolean show_abcd;
GtkWidget *w=linphone_gtk_get_main_window();
GHashTable *contacts_history;
contacts_history=g_hash_table_new_full(g_str_hash, g_str_equal,g_free, NULL);
g_object_set_data(G_OBJECT(w),"history",(gpointer)contacts_history);
if (!config_loaded){
title=linphone_gtk_get_ui_config("title","Linphone");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment