linphonecore.c 106 KB
Newer Older
aymeric's avatar
aymeric committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
linphone
Copyright (C) 2000  Simon MORLAT (simon.morlat@linphone.org)

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 "linphonecore.h"
smorlat's avatar
smorlat committed
21
#include "sipsetup.h"
aymeric's avatar
aymeric committed
22 23 24
#include "lpconfig.h"
#include "private.h"
#include "mediastreamer2/mediastream.h"
smorlat's avatar
smorlat committed
25
#include "mediastreamer2/msvolume.h"
26
#include "mediastreamer2/msequalizer.h"
aymeric's avatar
aymeric committed
27 28 29 30

#include <ortp/telephonyevents.h>


31
#ifdef INET6
aymeric's avatar
aymeric committed
32
#ifndef WIN32
33
#include <netdb.h>
aymeric's avatar
aymeric committed
34 35 36
#endif
#endif

smorlat's avatar
smorlat committed
37
/*#define UNSTANDART_GSM_11K 1*/
aymeric's avatar
aymeric committed
38 39

static const char *liblinphone_version=LIBLINPHONE_VERSION;
40
static void set_network_reachable(LinphoneCore* lc,bool_t isReachable);
aymeric's avatar
aymeric committed
41 42 43 44 45 46 47 48 49

#include "enum.h"

void linphone_core_get_local_ip(LinphoneCore *lc, const char *dest, char *result);
static void toggle_video_preview(LinphoneCore *lc, bool_t val);

/* relative path where is stored local ring*/
#define LOCAL_RING "rings/oldphone.wav"
/* same for remote ring (ringback)*/
50
#define REMOTE_RING "ringback.wav"
aymeric's avatar
aymeric committed
51

Simon Morlat's avatar
Simon Morlat committed
52
extern SalCallbacks linphone_sal_callbacks;
aymeric's avatar
aymeric committed
53 54 55 56 57 58 59 60 61 62 63 64

void lc_callback_obj_init(LCCallbackObj *obj,LinphoneCoreCbFunc func,void* ud)
{
  obj->_func=func;
  obj->_user_data=ud;
}

int lc_callback_obj_invoke(LCCallbackObj *obj, LinphoneCore *lc){
	if (obj->_func!=NULL) obj->_func(lc,obj->_user_data);
	return 0;
}

65

66
static MSList *make_codec_list(LinphoneCore *lc, const MSList *codecs, bool_t only_one_codec){
67 68 69 70
	MSList *l=NULL;
	const MSList *it;
	for(it=codecs;it!=NULL;it=it->next){
		PayloadType *pt=(PayloadType*)it->data;
71
		if ((pt->flags & PAYLOAD_TYPE_ENABLED) && linphone_core_check_payload_type_usability(lc,pt)){
72
			l=ms_list_append(l,payload_type_clone(pt));
73
			if (only_one_codec) break;
74 75 76 77 78 79
		}
	}
	return l;
}

static SalMediaDescription *create_local_media_description(LinphoneCore *lc, 
80
    		const char *localip, const char *username, bool_t only_one_codec){
81 82 83 84 85 86
	MSList *l;
	PayloadType *pt;
	SalMediaDescription *md=sal_media_description_new();
	md->nstreams=1;
	strncpy(md->addr,localip,sizeof(md->addr));
	strncpy(md->username,username,sizeof(md->username));
87
	md->bandwidth=linphone_core_get_download_bandwidth(lc);
88 89 90 91 92
	/*set audio capabilities */
	strncpy(md->streams[0].addr,localip,sizeof(md->streams[0].addr));
	md->streams[0].port=linphone_core_get_audio_port(lc);
	md->streams[0].proto=SalProtoRtpAvp;
	md->streams[0].type=SalAudio;
93
	md->streams[0].ptime=lc->net_conf.down_ptime;
94
	l=make_codec_list(lc,lc->codecs_conf.audio_codecs,only_one_codec);
95 96 97 98 99 100 101 102 103 104 105 106
	pt=payload_type_clone(rtp_profile_get_payload_from_mime(&av_profile,"telephone-event"));
	l=ms_list_append(l,pt);
	md->streams[0].payloads=l;
	
	if (lc->dw_audio_bw>0)
		md->streams[0].bandwidth=lc->dw_audio_bw;

	if (linphone_core_video_enabled (lc)){
		md->nstreams++;
		md->streams[1].port=linphone_core_get_video_port(lc);
		md->streams[1].proto=SalProtoRtpAvp;
		md->streams[1].type=SalVideo;
107
		l=make_codec_list(lc,lc->codecs_conf.video_codecs,only_one_codec);
108 109 110 111 112 113 114 115
		md->streams[1].payloads=l;
		if (lc->dw_video_bw)
			md->streams[1].bandwidth=lc->dw_video_bw;
	}
	return md;
}

static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from, LinphoneAddress *to){
aymeric's avatar
aymeric committed
116 117
	call->state=LCStateInit;
	call->start_time=time(NULL);
smorlat's avatar
smorlat committed
118
	call->media_start_time=0;
aymeric's avatar
aymeric committed
119 120
	call->log=linphone_call_log_new(call, from, to);
	linphone_core_notify_all_friends(call->core,LINPHONE_STATUS_ONTHEPHONE);
121
	if (linphone_core_get_firewall_policy(call->core)==LINPHONE_POLICY_USE_STUN)
smorlat's avatar
smorlat committed
122
		linphone_core_run_stun_tests(call->core,call);
aymeric's avatar
aymeric committed
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
}

static void discover_mtu(LinphoneCore *lc, const char *remote){
	int mtu;
	if (lc->net_conf.mtu==0	){
		/*attempt to discover mtu*/
		mtu=ms_discover_mtu(remote);
		if (mtu>0){
			ms_set_mtu(mtu);
			ms_message("Discovered mtu is %i, RTP payload max size is %i",
				mtu, ms_get_payload_max_size());
		}
	}
}

138
LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to)
aymeric's avatar
aymeric committed
139 140 141
{
	LinphoneCall *call=ms_new0(LinphoneCall,1);
	call->dir=LinphoneCallOutgoing;
142
	call->op=sal_op_new(lc->sal);
143
	sal_op_set_user_pointer(call->op,call);
aymeric's avatar
aymeric committed
144
	call->core=lc;
145
	linphone_core_get_local_ip(lc,linphone_address_get_domain(to),call->localip);
146
	call->localdesc=create_local_media_description (lc,call->localip,
147
		linphone_address_get_username(from),FALSE);
148
	linphone_call_init_common(call,from,to);
149
	discover_mtu(lc,linphone_address_get_domain (to));
aymeric's avatar
aymeric committed
150 151 152
	return call;
}

153
LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, SalOp *op){
aymeric's avatar
aymeric committed
154
	LinphoneCall *call=ms_new0(LinphoneCall,1);
155
	LinphoneAddress *me=linphone_core_get_primary_contact_parsed(lc);
156 157
	char *to_str;
	char *from_str;
smorlat's avatar
smorlat committed
158

aymeric's avatar
aymeric committed
159
	call->dir=LinphoneCallIncoming;
Simon Morlat's avatar
Simon Morlat committed
160
	sal_op_set_user_pointer(op,call);
161
	call->op=op;
aymeric's avatar
aymeric committed
162
	call->core=lc;
163 164 165 166 167 168 169 170 171 172 173 174

	if (lc->sip_conf.ping_with_options){
		/*the following sends an option request back to the caller so that
		 we get a chance to discover our nat'd address before answering.*/
		call->ping_op=sal_op_new(lc->sal);
		to_str=linphone_address_as_string(to);
		from_str=linphone_address_as_string(from);
		sal_op_set_route(call->ping_op,sal_op_get_network_origin(call->op));
		sal_ping(call->ping_op,to_str,from_str);
		ms_free(to_str);
		ms_free(from_str);
	}
175
	
176 177
	linphone_address_clean(from);
	linphone_core_get_local_ip(lc,linphone_address_get_domain(from),call->localip);
178
	call->localdesc=create_local_media_description (lc,call->localip,
179
	    linphone_address_get_username(me),lc->sip_conf.only_one_codec);
180
	linphone_call_init_common(call, from, to);
181 182
	discover_mtu(lc,linphone_address_get_domain(from));
	linphone_address_destroy(me);
aymeric's avatar
aymeric committed
183 184 185 186 187 188 189
	return call;
}

void linphone_call_destroy(LinphoneCall *obj)
{
	linphone_core_notify_all_friends(obj->core,obj->core->prev_mode);
	linphone_call_log_completed(obj->log,obj);
190
	linphone_core_update_allocated_audio_bandwidth(obj->core);
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
	if (obj->op!=NULL) {
		sal_op_release(obj->op);
		obj->op=NULL;
	}
	if (obj->resultdesc!=NULL) {
		sal_media_description_unref(obj->resultdesc);
		obj->resultdesc=NULL;
	}
	if (obj->localdesc!=NULL) {
		sal_media_description_unref(obj->localdesc);
		obj->localdesc=NULL;
	}
	if (obj->ping_op) {
		sal_op_release(obj->ping_op);
	}
aymeric's avatar
aymeric committed
206 207 208 209 210
	ms_free(obj);
}

/*prevent a gcc bug with %c*/
static size_t my_strftime(char *s, size_t max, const char  *fmt,  const struct tm *tm){
Jehan Monnier's avatar
Jehan Monnier committed
211
#if !defined(_WIN32_WCE)
aymeric's avatar
aymeric committed
212
	return strftime(s, max, fmt, tm);
Jehan Monnier's avatar
Jehan Monnier committed
213 214 215 216
#else
	return 0;
	/*FIXME*/
#endif /*_WIN32_WCE*/
aymeric's avatar
aymeric committed
217 218
}

219 220 221 222
static void set_call_log_date(LinphoneCallLog *cl, const struct tm *loctime){
	my_strftime(cl->start_date,sizeof(cl->start_date),"%c",loctime);
}

223
LinphoneCallLog * linphone_call_log_new(LinphoneCall *call, LinphoneAddress *from, LinphoneAddress *to){
aymeric's avatar
aymeric committed
224 225 226 227
	LinphoneCallLog *cl=ms_new0(LinphoneCallLog,1);
	struct tm loctime;
	cl->dir=call->dir;
#ifdef WIN32
Jehan Monnier's avatar
Jehan Monnier committed
228
#if !defined(_WIN32_WCE)
aymeric's avatar
aymeric committed
229
	loctime=*localtime(&call->start_time);
Jehan Monnier's avatar
Jehan Monnier committed
230 231
	/*FIXME*/
#endif /*_WIN32_WCE*/
aymeric's avatar
aymeric committed
232 233 234
#else
	localtime_r(&call->start_time,&loctime);
#endif
235
	set_call_log_date(cl,&loctime);
aymeric's avatar
aymeric committed
236 237 238 239
	cl->from=from;
	cl->to=to;
	return cl;
}
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296

static void call_logs_write_to_config_file(LinphoneCore *lc){
	MSList *elem;
	char logsection[32];
	int i;
	char *tmp;
	LpConfig *cfg=lc->config;

	if (!lc->ready) return;
	
	for(i=0,elem=lc->call_logs;elem!=NULL;elem=elem->next,++i){
		LinphoneCallLog *cl=(LinphoneCallLog*)elem->data;
		snprintf(logsection,sizeof(logsection),"call_log_%i",i);
		lp_config_set_int(cfg,logsection,"dir",cl->dir);
		lp_config_set_int(cfg,logsection,"status",cl->status);
		tmp=linphone_address_as_string(cl->from);
		lp_config_set_string(cfg,logsection,"from",tmp);
		ms_free(tmp);
		tmp=linphone_address_as_string(cl->to);
		lp_config_set_string(cfg,logsection,"to",tmp);
		ms_free(tmp);
		lp_config_set_string(cfg,logsection,"start_date",cl->start_date);
		lp_config_set_int(cfg,logsection,"duration",cl->duration);
		if (cl->refkey) lp_config_set_string(cfg,logsection,"refkey",cl->refkey);
	}
	for(;i<lc->max_call_logs;++i){
		snprintf(logsection,sizeof(logsection),"call_log_%i",i);
		lp_config_clean_section(cfg,logsection);
	}
}

static void call_logs_read_from_config_file(LinphoneCore *lc){
	char logsection[32];
	int i;
	const char *tmp;
	LpConfig *cfg=lc->config;
	for(i=0;;++i){
		snprintf(logsection,sizeof(logsection),"call_log_%i",i);
		if (lp_config_has_section(cfg,logsection)){
			LinphoneCallLog *cl=ms_new0(LinphoneCallLog,1);
			cl->dir=lp_config_get_int(cfg,logsection,"dir",0);
			cl->status=lp_config_get_int(cfg,logsection,"status",0);
			tmp=lp_config_get_string(cfg,logsection,"from",NULL);
			if (tmp) cl->from=linphone_address_new(tmp);
			tmp=lp_config_get_string(cfg,logsection,"to",NULL);
			if (tmp) cl->to=linphone_address_new(tmp);
			tmp=lp_config_get_string(cfg,logsection,"start_date",NULL);
			if (tmp) strncpy(cl->start_date,tmp,sizeof(cl->start_date));
			cl->duration=lp_config_get_int(cfg,logsection,"duration",0);
			tmp=lp_config_get_string(cfg,logsection,"refkey",NULL);
			if (tmp) cl->refkey=ms_strdup(tmp);
			lc->call_logs=ms_list_append(lc->call_logs,cl);
		}else break;	
	}
}


aymeric's avatar
aymeric committed
297 298
void linphone_call_log_completed(LinphoneCallLog *calllog, LinphoneCall *call){
	LinphoneCore *lc=call->core;
299
	
aymeric's avatar
aymeric committed
300 301 302
	calllog->duration=time(NULL)-call->start_time;
	switch(call->state){
		case LCStateInit:
303
		case LCStatePreEstablishing:
aymeric's avatar
aymeric committed
304 305 306 307 308 309 310
			calllog->status=LinphoneCallAborted;
			break;
		case LCStateRinging:
			if (calllog->dir==LinphoneCallIncoming){
				char *info;
				calllog->status=LinphoneCallMissed;
				lc->missed_calls++;
311 312 313
				info=ortp_strdup_printf(ngettext("You have missed %i call.",
                            "You have missed %i calls.", lc->missed_calls),
                        lc->missed_calls);
aymeric's avatar
aymeric committed
314 315 316 317 318 319 320 321 322
				lc->vtable.display_status(lc,info);
				ms_free(info);
			}
			else calllog->status=LinphoneCallAborted;
			break;
		case LCStateAVRunning:
			calllog->status=LinphoneCallSuccess;
			break;
	}
Simon Morlat's avatar
Simon Morlat committed
323
	lc->call_logs=ms_list_prepend(lc->call_logs,(void *)calllog);
aymeric's avatar
aymeric committed
324
	if (ms_list_size(lc->call_logs)>lc->max_call_logs){
Simon Morlat's avatar
Simon Morlat committed
325 326 327 328 329 330
		MSList *elem,*prevelem=NULL;
		/*find the last element*/
		for(elem=lc->call_logs;elem!=NULL;elem=elem->next){
			prevelem=elem;
		}
		elem=prevelem;
aymeric's avatar
aymeric committed
331 332 333 334 335 336
		linphone_call_log_destroy((LinphoneCallLog*)elem->data);
		lc->call_logs=ms_list_remove_link(lc->call_logs,elem);
	}
	if (lc->vtable.call_log_updated!=NULL){
		lc->vtable.call_log_updated(lc,calllog);
	}
337
	call_logs_write_to_config_file(lc);
aymeric's avatar
aymeric committed
338 339
}

smorlat's avatar
smorlat committed
340 341 342 343 344 345 346 347 348 349
/**
 * @addtogroup call_logs
 * @{
**/

/**
 * Returns a human readable string describing the call.
 * 
 * @note: the returned char* must be freed by the application (use ms_free()).
**/
aymeric's avatar
aymeric committed
350 351
char * linphone_call_log_to_str(LinphoneCallLog *cl){
	char *status;
352
	char *tmp;
353 354
	char *from=linphone_address_as_string (cl->from);
	char *to=linphone_address_as_string (cl->to);
aymeric's avatar
aymeric committed
355 356 357 358 359 360 361 362 363 364 365 366 367
	switch(cl->status){
		case LinphoneCallAborted:
			status=_("aborted");
			break;
		case LinphoneCallSuccess:
			status=_("completed");
			break;
		case LinphoneCallMissed:
			status=_("missed");
			break;
		default:
			status="unknown";
	}
368
	tmp=ortp_strdup_printf(_("%s at %s\nFrom: %s\nTo: %s\nStatus: %s\nDuration: %i mn %i sec\n"),
aymeric's avatar
aymeric committed
369 370
			(cl->dir==LinphoneCallIncoming) ? _("Incoming call") : _("Outgoing call"),
			cl->start_date,
371 372
			from,
			to,
aymeric's avatar
aymeric committed
373 374 375
			status,
			cl->duration/60,
			cl->duration%60);
376 377 378
	ms_free(from);
	ms_free(to);
	return tmp;
aymeric's avatar
aymeric committed
379 380
}

smorlat's avatar
smorlat committed
381 382 383 384 385 386 387 388
void linphone_call_log_set_user_pointer(LinphoneCallLog *cl, void *up){
	cl->user_pointer=up;
}

void *linphone_call_log_get_user_pointer(const LinphoneCallLog *cl){
	return cl->user_pointer;
}

smorlat's avatar
smorlat committed
389 390


391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417
/**
 * Associate a persistent reference key to the call log.
 *
 * The reference key can be for example an id to an external database.
 * It is stored in the config file, thus can survive to process exits/restarts.
 *
**/
void linphone_call_log_set_ref_key(LinphoneCallLog *cl, const char *refkey){
	if (cl->refkey!=NULL){
		ms_free(cl->refkey);
		cl->refkey=NULL;
	}
	if (refkey) cl->refkey=ms_strdup(refkey);
	call_logs_write_to_config_file(cl->lc);
}

/**
 * Get the persistent reference key associated to the call log.
 *
 * The reference key can be for example an id to an external database.
 * It is stored in the config file, thus can survive to process exits/restarts.
 *
**/
const char *linphone_call_log_get_ref_key(const LinphoneCallLog *cl){
	return cl->refkey;
}

smorlat's avatar
smorlat committed
418 419
/** @} */

aymeric's avatar
aymeric committed
420
void linphone_call_log_destroy(LinphoneCallLog *cl){
421 422 423
	if (cl->from!=NULL) linphone_address_destroy(cl->from);
	if (cl->to!=NULL) linphone_address_destroy(cl->to);
	if (cl->refkey!=NULL) ms_free(cl->refkey);
aymeric's avatar
aymeric committed
424 425 426
	ms_free(cl);
}

427 428 429 430 431 432 433 434 435 436 437 438
/**
 * Returns TRUE if the LinphoneCall asked to autoanswer
 *
**/
bool_t linphone_call_asked_to_autoanswer(LinphoneCall *call){
	//return TRUE if the unique(for the moment) incoming call asked to be autoanswered
	if(call)
		return sal_call_autoanswer_asked(call->op);
	else
		return FALSE;
}

smorlat's avatar
smorlat committed
439 440 441
int linphone_core_get_current_call_duration(const LinphoneCore *lc){
	LinphoneCall *call=lc->call;
	if (call==NULL) return 0;
smorlat's avatar
smorlat committed
442 443 444 445
	if (call->media_start_time==0) return 0;
	return time(NULL)-call->media_start_time;
}

446
const LinphoneAddress *linphone_core_get_remote_uri(LinphoneCore *lc){
smorlat's avatar
smorlat committed
447 448 449
	LinphoneCall *call=lc->call;
	if (call==NULL) return 0;
	return call->dir==LinphoneCallIncoming ? call->log->from : call->log->to;
smorlat's avatar
smorlat committed
450 451
}

452 453 454 455 456 457 458 459
/**
 * Enable logs in supplied FILE*.
 *
 * @ingroup misc
 *
 * @param file a C FILE* where to fprintf logs. If null stdout is used.
 * 
**/
aymeric's avatar
aymeric committed
460 461 462 463 464 465
void linphone_core_enable_logs(FILE *file){
	if (file==NULL) file=stdout;
	ortp_set_log_file(file);
	ortp_set_log_level_mask(ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL);
}

466 467 468 469 470 471 472 473 474
/**
 * Enable logs through the user's supplied log callback.
 *
 * @ingroup misc
 *
 * @param logfunc The address of a OrtpLogFunc callback whose protoype is
 *            	  typedef void (*OrtpLogFunc)(OrtpLogLevel lev, const char *fmt, va_list args);
 * 
**/
aymeric's avatar
aymeric committed
475 476 477 478 479
void linphone_core_enable_logs_with_cb(OrtpLogFunc logfunc){
	ortp_set_log_level_mask(ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL);
	ortp_set_log_handler(logfunc);
}

480 481 482 483 484
/**
 * Entirely disable logging.
 *
 * @ingroup misc
**/
aymeric's avatar
aymeric committed
485 486 487 488 489
void linphone_core_disable_logs(){
	ortp_set_log_level_mask(ORTP_ERROR|ORTP_FATAL);
}


490
static void
aymeric's avatar
aymeric committed
491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510
net_config_read (LinphoneCore *lc)
{
	int tmp;
	const char *tmpstr;
	LpConfig *config=lc->config;

	tmp=lp_config_get_int(config,"net","download_bw",0);
	linphone_core_set_download_bandwidth(lc,tmp);
	tmp=lp_config_get_int(config,"net","upload_bw",0);
	linphone_core_set_upload_bandwidth(lc,tmp);
	linphone_core_set_stun_server(lc,lp_config_get_string(config,"net","stun_server",NULL));
	tmpstr=lp_config_get_string(lc->config,"net","nat_address",NULL);
	if (tmpstr!=NULL && (strlen(tmpstr)<1)) tmpstr=NULL;
	linphone_core_set_nat_address(lc,tmpstr);
	tmp=lp_config_get_int(lc->config,"net","firewall_policy",0);
	linphone_core_set_firewall_policy(lc,tmp);
	tmp=lp_config_get_int(lc->config,"net","nat_sdp_only",0);
	lc->net_conf.nat_sdp_only=tmp;
	tmp=lp_config_get_int(lc->config,"net","mtu",0);
	linphone_core_set_mtu(lc,tmp);
jehan's avatar
jehan committed
511 512 513
	tmp=lp_config_get_int(lc->config,"net","download_ptime",0);
	linphone_core_set_download_ptime(lc,tmp);

aymeric's avatar
aymeric committed
514 515
}

516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531
static void build_sound_devices_table(LinphoneCore *lc){
	const char **devices;
	const char **old;
	int ndev;
	int i;
	const MSList *elem=ms_snd_card_manager_get_list(ms_snd_card_manager_get());
	ndev=ms_list_size(elem);
	devices=ms_malloc((ndev+1)*sizeof(const char *));
	for (i=0;elem!=NULL;elem=elem->next,i++){
		devices[i]=ms_snd_card_get_string_id((MSSndCard *)elem->data);
	}
	devices[ndev]=NULL;
	old=lc->sound_conf.cards;
	lc->sound_conf.cards=devices;
	if (old!=NULL) ms_free(old);
}
aymeric's avatar
aymeric committed
532

533
static void sound_config_read(LinphoneCore *lc)
aymeric's avatar
aymeric committed
534 535 536 537
{
	/*int tmp;*/
	const char *tmpbuf;
	const char *devid;
538
	float gain=0;
539
#ifdef __linux
aymeric's avatar
aymeric committed
540 541 542 543 544 545 546 547
	/*alsadev let the user use custom alsa device within linphone*/
	devid=lp_config_get_string(lc->config,"sound","alsadev",NULL);
	if (devid){
		MSSndCard *card=ms_alsa_card_new_custom(devid,devid);
		ms_snd_card_manager_add_card(ms_snd_card_manager_get(),card);
	}
#endif
	/* retrieve all sound devices */
548 549
	build_sound_devices_table(lc);

aymeric's avatar
aymeric committed
550 551
	devid=lp_config_get_string(lc->config,"sound","playback_dev_id",NULL);
	linphone_core_set_playback_device(lc,devid);
552

aymeric's avatar
aymeric committed
553 554
	devid=lp_config_get_string(lc->config,"sound","ringer_dev_id",NULL);
	linphone_core_set_ringer_device(lc,devid);
555

aymeric's avatar
aymeric committed
556 557
	devid=lp_config_get_string(lc->config,"sound","capture_dev_id",NULL);
	linphone_core_set_capture_device(lc,devid);
558

aymeric's avatar
aymeric committed
559 560 561 562 563 564 565 566 567 568
/*
	tmp=lp_config_get_int(lc->config,"sound","play_lev",80);
	linphone_core_set_play_level(lc,tmp);
	tmp=lp_config_get_int(lc->config,"sound","ring_lev",80);
	linphone_core_set_ring_level(lc,tmp);
	tmp=lp_config_get_int(lc->config,"sound","rec_lev",80);
	linphone_core_set_rec_level(lc,tmp);
	tmpbuf=lp_config_get_string(lc->config,"sound","source","m");
	linphone_core_set_sound_source(lc,tmpbuf[0]);
*/
569

aymeric's avatar
aymeric committed
570 571
	tmpbuf=PACKAGE_SOUND_DIR "/" LOCAL_RING;
	tmpbuf=lp_config_get_string(lc->config,"sound","local_ring",tmpbuf);
Jehan Monnier's avatar
Jehan Monnier committed
572
	if (ortp_file_exist(tmpbuf)==-1) {
aymeric's avatar
aymeric committed
573 574 575 576 577 578
		tmpbuf=PACKAGE_SOUND_DIR "/" LOCAL_RING;
	}
	if (strstr(tmpbuf,".wav")==NULL){
		/* it currently uses old sound files, so replace them */
		tmpbuf=PACKAGE_SOUND_DIR "/" LOCAL_RING;
	}
579

aymeric's avatar
aymeric committed
580
	linphone_core_set_ring(lc,tmpbuf);
581

582
	tmpbuf=PACKAGE_SOUND_DIR "/" REMOTE_RING;
aymeric's avatar
aymeric committed
583
	tmpbuf=lp_config_get_string(lc->config,"sound","remote_ring",tmpbuf);
Jehan Monnier's avatar
Jehan Monnier committed
584
	if (ortp_file_exist(tmpbuf)==-1){
585
		tmpbuf=PACKAGE_SOUND_DIR "/" REMOTE_RING;
aymeric's avatar
aymeric committed
586 587 588
	}
	if (strstr(tmpbuf,".wav")==NULL){
		/* it currently uses old sound files, so replace them */
589
		tmpbuf=PACKAGE_SOUND_DIR "/" REMOTE_RING;
aymeric's avatar
aymeric committed
590
	}
591
	linphone_core_set_ringback(lc,tmpbuf);
aymeric's avatar
aymeric committed
592 593 594
	check_sound_device(lc);
	lc->sound_conf.latency=0;

595 596 597 598
	linphone_core_enable_echo_cancellation(lc,
	    lp_config_get_int(lc->config,"sound","echocancelation",0) |
	    lp_config_get_int(lc->config,"sound","echocancellation",0)
		);
smorlat's avatar
smorlat committed
599 600 601

	linphone_core_enable_echo_limiter(lc,
		lp_config_get_int(lc->config,"sound","echolimiter",0));
602 603
	linphone_core_enable_agc(lc,
		lp_config_get_int(lc->config,"sound","agc",0));
604 605 606

	gain=lp_config_get_float(lc->config,"sound","soft_play_lev",0);
		linphone_core_set_soft_play_level(lc,gain);
aymeric's avatar
aymeric committed
607 608
}

609
static void sip_config_read(LinphoneCore *lc)
aymeric's avatar
aymeric committed
610 611 612 613 614 615 616 617 618
{
	char *contact;
	const char *tmpstr;
	int port;
	int i,tmp;
	int ipv6;
	port=lp_config_get_int(lc->config,"sip","use_info",0);
	linphone_core_set_use_info_for_dtmf(lc,port);

619 620 621
	port=lp_config_get_int(lc->config,"sip","use_rfc2833",0);
	linphone_core_set_use_rfc2833_for_dtmf(lc,port);

aymeric's avatar
aymeric committed
622 623 624 625 626 627 628 629 630 631
	ipv6=lp_config_get_int(lc->config,"sip","use_ipv6",-1);
	if (ipv6==-1){
		ipv6=0;
		if (host_has_ipv6_network()){
			lc->vtable.display_message(lc,_("Your machine appears to be connected to an IPv6 network. By default linphone always uses IPv4. Please update your configuration if you want to use IPv6"));
		}
	}
	linphone_core_enable_ipv6(lc,ipv6);
	port=lp_config_get_int(lc->config,"sip","sip_port",5060);
	linphone_core_set_sip_port(lc,port);
632

aymeric's avatar
aymeric committed
633 634
	tmpstr=lp_config_get_string(lc->config,"sip","contact",NULL);
	if (tmpstr==NULL || linphone_core_set_primary_contact(lc,tmpstr)==-1) {
smorlat's avatar
smorlat committed
635 636
		const char *hostname=NULL;
		const char *username=NULL;
637
#ifdef HAVE_GETENV
smorlat's avatar
smorlat committed
638 639
		hostname=getenv("HOST");
		username=getenv("USER");
aymeric's avatar
aymeric committed
640
		if (hostname==NULL) hostname=getenv("HOSTNAME");
641
#endif /*HAVE_GETENV*/
aymeric's avatar
aymeric committed
642 643 644 645 646 647 648 649 650 651 652 653
		if (hostname==NULL)
			hostname="unknown-host";
		if (username==NULL){
			username="toto";
		}
		contact=ortp_strdup_printf("sip:%s@%s",username,hostname);
		linphone_core_set_primary_contact(lc,contact);
		ms_free(contact);
	}

	tmp=lp_config_get_int(lc->config,"sip","guess_hostname",1);
	linphone_core_set_guess_hostname(lc,tmp);
654 655


aymeric's avatar
aymeric committed
656 657 658 659 660 661 662 663 664 665 666 667 668 669 670
	tmp=lp_config_get_int(lc->config,"sip","inc_timeout",15);
	linphone_core_set_inc_timeout(lc,tmp);

	/* get proxies config */
	for(i=0;; i++){
		LinphoneProxyConfig *cfg=linphone_proxy_config_new_from_config_file(lc->config,i);
		if (cfg!=NULL){
			linphone_core_add_proxy_config(lc,cfg);
		}else{
			break;
		}
	}
	/* get the default proxy */
	tmp=lp_config_get_int(lc->config,"sip","default_proxy",-1);
	linphone_core_set_default_proxy_index(lc,tmp);
671

aymeric's avatar
aymeric committed
672 673 674 675 676
	/* read authentication information */
	for(i=0;; i++){
		LinphoneAuthInfo *ai=linphone_auth_info_new_from_config_file(lc->config,i);
		if (ai!=NULL){
			linphone_core_add_auth_info(lc,ai);
Simon Morlat's avatar
Simon Morlat committed
677
			linphone_auth_info_destroy(ai);
aymeric's avatar
aymeric committed
678 679 680 681
		}else{
			break;
		}
	}
682
	
683
	/*for tuning or test*/
aymeric's avatar
aymeric committed
684
	lc->sip_conf.sdp_200_ack=lp_config_get_int(lc->config,"sip","sdp_200_ack",0);
smorlat's avatar
smorlat committed
685
	lc->sip_conf.only_one_codec=lp_config_get_int(lc->config,"sip","only_one_codec",0);
686
	lc->sip_conf.register_only_when_network_is_up=
687
		lp_config_get_int(lc->config,"sip","register_only_when_network_is_up",1);
688
	lc->sip_conf.ping_with_options=lp_config_get_int(lc->config,"sip","ping_with_options",1);
jehan's avatar
jehan committed
689
	lc->sip_conf.auto_net_state_mon=lp_config_get_int(lc->config,"sip","auto_net_state_mon",1);
aymeric's avatar
aymeric committed
690 691
}

692
static void rtp_config_read(LinphoneCore *lc)
aymeric's avatar
aymeric committed
693 694 695 696 697 698
{
	int port;
	int jitt_comp;
	int nortp_timeout;
	port=lp_config_get_int(lc->config,"rtp","audio_rtp_port",7078);
	linphone_core_set_audio_port(lc,port);
699

aymeric's avatar
aymeric committed
700 701 702
	port=lp_config_get_int(lc->config,"rtp","video_rtp_port",9078);
	if (port==0) port=9078;
	linphone_core_set_video_port(lc,port);
703

aymeric's avatar
aymeric committed
704
	jitt_comp=lp_config_get_int(lc->config,"rtp","audio_jitt_comp",60);
705
	linphone_core_set_audio_jittcomp(lc,jitt_comp);
aymeric's avatar
aymeric committed
706 707
	jitt_comp=lp_config_get_int(lc->config,"rtp","video_jitt_comp",60);
	nortp_timeout=lp_config_get_int(lc->config,"rtp","nortp_timeout",30);
708
	linphone_core_set_nortp_timeout(lc,nortp_timeout);
aymeric's avatar
aymeric committed
709 710
}

711 712 713 714 715 716 717 718
static PayloadType * find_payload(RtpProfile *prof, const char *mime_type, int clock_rate, const char *recv_fmtp){
	PayloadType *candidate=NULL;
	int i;
	PayloadType *it;
	for(i=0;i<127;++i){
		it=rtp_profile_get_payload(prof,i);
		if (it!=NULL && strcasecmp(mime_type,it->mime_type)==0
			&& (clock_rate==it->clock_rate || clock_rate<=0) ){
719
			if ( (recv_fmtp && it->recv_fmtp && strstr(recv_fmtp,it->recv_fmtp)!=NULL) ||
720 721
				(recv_fmtp==NULL && it->recv_fmtp==NULL) ){
				/*exact match*/
722
				if (recv_fmtp) payload_type_set_recv_fmtp(it,recv_fmtp);
723
				return it;
724 725 726 727 728
			}else {
				if (candidate){
					if (it->recv_fmtp==NULL) candidate=it;
				}else candidate=it;
			}
729 730
		}
	}
731 732 733
	if (candidate && recv_fmtp){
		payload_type_set_recv_fmtp(candidate,recv_fmtp);
	}
734 735
	return candidate;
}
aymeric's avatar
aymeric committed
736

737
static bool_t get_codec(LpConfig *config, char* type, int index, PayloadType **ret){
aymeric's avatar
aymeric committed
738 739 740 741
	char codeckey[50];
	const char *mime,*fmtp;
	int rate,enabled;
	PayloadType *pt;
742

743
	*ret=NULL;
aymeric's avatar
aymeric committed
744 745
	snprintf(codeckey,50,"%s_%i",type,index);
	mime=lp_config_get_string(config,codeckey,"mime",NULL);
746
	if (mime==NULL || strlen(mime)==0 ) return FALSE;
747

aymeric's avatar
aymeric committed
748 749 750
	rate=lp_config_get_int(config,codeckey,"rate",8000);
	fmtp=lp_config_get_string(config,codeckey,"recv_fmtp",NULL);
	enabled=lp_config_get_int(config,codeckey,"enabled",1);
751 752
	pt=find_payload(&av_profile,mime,rate,fmtp);
	if (pt && enabled ) pt->flags|=PAYLOAD_TYPE_ENABLED;
aymeric's avatar
aymeric committed
753
	//ms_message("Found codec %s/%i",pt->mime_type,pt->clock_rate);
754 755 756 757 758 759
	if (pt==NULL) ms_warning("Ignoring codec config %s/%i with fmtp=%s because unsupported",
	    		mime,rate,fmtp ? fmtp : "");
	*ret=pt;
	return TRUE;
}

760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787
static const char *codec_pref_order[]={
	"speex",
	"gsm",
	"pcmu",
	"pcma",
	"H264",
	"MP4V-ES",
	"theora",
	"H263-1998",
	"H263",
	NULL,
};

static int find_codec_rank(const char *mime){
	int i;
	for(i=0;codec_pref_order[i]!=NULL;++i){
		if (strcasecmp(codec_pref_order[i],mime)==0)
			break;
	}
	return i;
}

static int codec_compare(const PayloadType *a, const PayloadType *b){
	int ra,rb;
	ra=find_codec_rank(a->mime_type);
	rb=find_codec_rank(b->mime_type);
	if (ra>rb) return 1;
	if (ra<rb) return -1;
788
	return 0;
789 790
}

791 792 793 794 795 796 797 798 799 800 801 802 803
static MSList *add_missing_codecs(SalStreamType mtype, MSList *l){
	int i;
	for(i=0;i<127;++i){
		PayloadType *pt=rtp_profile_get_payload(&av_profile,i);
		if (pt){
			if (mtype==SalVideo && pt->type!=PAYLOAD_VIDEO)
				pt=NULL;
			else if (mtype==SalAudio && (pt->type!=PAYLOAD_AUDIO_PACKETIZED 
			    && pt->type!=PAYLOAD_AUDIO_CONTINUOUS)){
				pt=NULL;
			}
			if (pt && ms_filter_codec_supported(pt->mime_type)){
				if (ms_list_find(l,pt)==NULL){
Simon Morlat's avatar
Simon Morlat committed
804
					payload_type_set_flag(pt,PAYLOAD_TYPE_ENABLED);
805 806
					ms_message("Adding new codec %s/%i with fmtp %s",
					    pt->mime_type,pt->clock_rate,pt->recv_fmtp ? pt->recv_fmtp : "");
807
					l=ms_list_insert_sorted(l,pt,(int (*)(const void *, const void *))codec_compare);
808 809 810 811 812
				}
			}
		}
	}
	return l;
aymeric's avatar
aymeric committed
813 814
}

815
static void codecs_config_read(LinphoneCore *lc)
aymeric's avatar
aymeric committed
816 817 818 819 820
{
	int i;
	PayloadType *pt;
	MSList *audio_codecs=NULL;
	MSList *video_codecs=NULL;
821 822 823 824 825 826
	for (i=0;get_codec(lc->config,"audio_codec",i,&pt);i++){
		if (pt){
			if (!ms_filter_codec_supported(pt->mime_type)){
				ms_warning("Codec %s is not supported by mediastreamer2, removed.",pt->mime_type);
			}else audio_codecs=ms_list_append(audio_codecs,pt);
		}
aymeric's avatar
aymeric committed
827
	}
828 829 830 831 832 833 834
	audio_codecs=add_missing_codecs(SalAudio,audio_codecs);
	for (i=0;get_codec(lc->config,"video_codec",i,&pt);i++){
		if (pt){
			if (!ms_filter_codec_supported(pt->mime_type)){
				ms_warning("Codec %s is not supported by mediastreamer2, removed.",pt->mime_type);
			}else video_codecs=ms_list_append(video_codecs,(void *)pt);
		}
aymeric's avatar
aymeric committed
835
	}
836
	video_codecs=add_missing_codecs(SalVideo,video_codecs);
aymeric's avatar
aymeric committed
837 838
	linphone_core_set_audio_codecs(lc,audio_codecs);
	linphone_core_set_video_codecs(lc,video_codecs);
839
	linphone_core_update_allocated_audio_bandwidth(lc);
aymeric's avatar
aymeric committed
840 841
}

842
static void video_config_read(LinphoneCore *lc){
Simon Morlat's avatar
Simon Morlat committed
843
	int capture, display, self_view;
aymeric's avatar
aymeric committed
844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863
	int enabled;
	const char *str;
	int ndev;
	const char **devices;
	const MSList *elem;
	int i;

	/* retrieve all video devices */
	elem=ms_web_cam_manager_get_list(ms_web_cam_manager_get());
	ndev=ms_list_size(elem);
	devices=ms_malloc((ndev+1)*sizeof(const char *));
	for (i=0;elem!=NULL;elem=elem->next,i++){
		devices[i]=ms_web_cam_get_string_id((MSWebCam *)elem->data);
	}
	devices[ndev]=NULL;
	lc->video_conf.cams=devices;

	str=lp_config_get_string(lc->config,"video","device",NULL);
	if (str && str[0]==0) str=NULL;
	linphone_core_set_video_device(lc,str);
864

smorlat's avatar
smorlat committed
865 866 867
	linphone_core_set_preferred_video_size_by_name(lc,
		lp_config_get_string(lc->config,"video","size","cif"));

aymeric's avatar
aymeric committed
868 869 870
	enabled=lp_config_get_int(lc->config,"video","enabled",1);
	capture=lp_config_get_int(lc->config,"video","capture",enabled);
	display=lp_config_get_int(lc->config,"video","display",enabled);
Simon Morlat's avatar
Simon Morlat committed
871
	self_view=lp_config_get_int(lc->config,"video","self_view",enabled);
aymeric's avatar
aymeric committed
872 873
#ifdef VIDEO_ENABLED
	linphone_core_enable_video(lc,capture,display);
Simon Morlat's avatar
Simon Morlat committed
874
	linphone_core_enable_self_view(lc,self_view);
aymeric's avatar
aymeric committed
875 876 877
#endif
}

878
static void ui_config_read(LinphoneCore *lc)
aymeric's avatar
aymeric committed
879 880 881 882 883 884
{
	LinphoneFriend *lf;
	int i;
	for (i=0;(lf=linphone_friend_new_from_config_file(lc,i))!=NULL;i++){
		linphone_core_add_friend(lc,lf);
	}
885
	call_logs_read_from_config_file(lc);
aymeric's avatar
aymeric committed
886 887
}

888 889
/*
static void autoreplier_config_init(LinphoneCore *lc)
aymeric's avatar
aymeric committed
890 891 892 893 894 895 896 897 898
{
	autoreplier_config_t *config=&lc->autoreplier_conf;
	config->enabled=lp_config_get_int(lc->config,"autoreplier","enabled",0);
	config->after_seconds=lp_config_get_int(lc->config,"autoreplier","after_seconds",6);
	config->max_users=lp_config_get_int(lc->config,"autoreplier","max_users",1);
	config->max_rec_time=lp_config_get_int(lc->config,"autoreplier","max_rec_time",60);
	config->max_rec_msg=lp_config_get_int(lc->config,"autoreplier","max_rec_msg",10);
	config->message=lp_config_get_string(lc->config,"autoreplier","message",NULL);
}
899
*/
aymeric's avatar
aymeric committed
900

901 902 903 904 905 906 907 908 909 910 911 912 913 914
/**
 * Sets maximum available download bandwidth
 *
 * @ingroup media_parameters
 *
 * This is IP bandwidth, in kbit/s.
 * This information is used signaled to other parties during
 * calls (within SDP messages) so that the remote end can have
 * sufficient knowledge to properly configure its audio & video
 * codec output bitrate to not overflow available bandwidth.
 *
 * @param lc the LinphoneCore object
 * @param bw the bandwidth in kbits/s, 0 for infinite
 */
aymeric's avatar
aymeric committed
915 916 917 918 919 920
void linphone_core_set_download_bandwidth(LinphoneCore *lc, int bw){
	lc->net_conf.download_bw=bw;
	if (bw==0){ /*infinite*/
		lc->dw_audio_bw=-1;
		lc->dw_video_bw=-1;
	}else {
921 922
		lc->dw_audio_bw=MIN(lc->audio_bw,bw);
		lc->dw_video_bw=MAX(bw-lc->dw_audio_bw-10,0);/*-10: security margin*/
aymeric's avatar
aymeric committed
923 924 925
	}
}

926 927 928 929 930 931 932 933 934 935 936 937 938
/**
 * Sets maximum available upload bandwidth
 *
 * @ingroup media_parameters
 *
 * This is IP bandwidth, in kbit/s.
 * This information is used by liblinphone together with remote
 * side available bandwidth signaled in SDP messages to properly
 * configure audio & video codec's output bitrate.
 *
 * @param lc the LinphoneCore object
 * @param bw the bandwidth in kbits/s, 0 for infinite
 */
aymeric's avatar
aymeric committed
939 940 941 942 943 944
void linphone_core_set_upload_bandwidth(LinphoneCore *lc, int bw){
	lc->net_conf.upload_bw=bw;
	if (bw==0){ /*infinite*/
		lc->up_audio_bw=-1;
		lc->up_video_bw=-1;
	}else{
945 946
		lc->up_audio_bw=MIN(lc->audio_bw,bw);
		lc->up_video_bw=MAX(bw-lc->up_audio_bw-10,0);/*-10: security margin*/
aymeric's avatar
aymeric committed
947 948 949
	}
}

950 951 952 953 954 955 956 957
/**
 * Retrieve the maximum available download bandwidth.
 *
 * @ingroup media_parameters
 *
 * This value was set by linphone_core_set_download_bandwidth().
 *
**/
aymeric's avatar
aymeric committed
958 959 960 961
int linphone_core_get_download_bandwidth(const LinphoneCore *lc){
	return lc->net_conf.download_bw;
}

962 963 964 965 966 967 968 969
/**
 * Retrieve the maximum available upload bandwidth.
 *
 * @ingroup media_parameters
 *
 * This value was set by linphone_core_set_upload_bandwidth().
 *
**/
aymeric's avatar
aymeric committed
970 971 972
int linphone_core_get_upload_bandwidth(const LinphoneCore *lc){
	return lc->net_conf.upload_bw;
}
jehan's avatar
jehan committed
973 974 975 976
/**
 * set audio packetization time linphone expect to received from peer
 */
void linphone_core_set_download_ptime(LinphoneCore *lc, int ptime) {
977
	lc->net_conf.down_ptime=ptime;
jehan's avatar
jehan committed
978
}
979

jehan's avatar
jehan committed
980
int  linphone_core_get_download_ptime(LinphoneCore *lc) {
981
	return lc->net_conf.down_ptime;
jehan's avatar
jehan committed
982 983
}

aymeric's avatar
aymeric committed
984

985 986 987 988 989 990
/**
 * Returns liblinphone's version as a string.
 *
 * @ingroup misc
 *
**/
aymeric's avatar
aymeric committed
991 992 993 994 995
const char * linphone_core_get_version(void){
	return liblinphone_version;
}


996
static MSList *linphone_payload_types=NULL;
aymeric's avatar
aymeric committed
997

998 999 1000
static void linphone_core_assign_payload_type(PayloadType *const_pt, int number, const char *recv_fmtp){
	PayloadType *pt;
	pt=payload_type_clone(const_pt);
1001
	payload_type_set_number(pt,number);
1002 1003
	if (recv_fmtp!=NULL) payload_type_set_recv_fmtp(pt,recv_fmtp);
	rtp_profile_set_payload(&av_profile,number,pt);
1004
	linphone_payload_types=ms_list_append(linphone_payload_types,pt);
1005 1006 1007 1008 1009 1010 1011
}

static void linphone_core_free_payload_types(void){
	ms_list_for_each(linphone_payload_types,(void (*)(void*))payload_type_destroy);
	ms_list_free(linphone_payload_types);
	linphone_payload_types=NULL;
}
1012

1013 1014
static void linphone_core_init (LinphoneCore * lc, const LinphoneCoreVTable *vtable, const char *config_path, 
    const char *factory_config_path, void * userdata)
aymeric's avatar
aymeric committed
1015 1016 1017
{
	memset (lc, 0, sizeof (LinphoneCore));
	lc->data=userdata;
smorlat's avatar
fixes  
smorlat committed
1018

aymeric's avatar
aymeric committed
1019 1020
	memcpy(&lc->vtable,vtable,sizeof(LinphoneCoreVTable));

smorlat's avatar
fixes  
smorlat committed
1021 1022
	gstate_initialize(lc);
	gstate_new_state(lc, GSTATE_POWER_STARTUP, NULL);
1023

aymeric's avatar
aymeric committed
1024
	ortp_init();
1025 1026 1027
	linphone_core_assign_payload_type(&payload_type_pcmu8000,0,NULL);
	linphone_core_assign_payload_type(&payload_type_gsm,3,NULL);
	linphone_core_assign_payload_type(&payload_type_pcma8000,8,NULL);
1028 1029 1030 1031
	linphone_core_assign_payload_type(&payload_type_lpc1015,115,NULL);
	linphone_core_assign_payload_type(&payload_type_speex_nb,110,"vbr=on");
	linphone_core_assign_payload_type(&payload_type_speex_wb,111,"vbr=on");
	linphone_core_assign_payload_type(&payload_type_speex_uwb,112,"vbr=on");
1032
	linphone_core_assign_payload_type(&payload_type_telephone_event,101,"0-11");
1033
	linphone_core_assign_payload_type(&payload_type_ilbc,113,"mode=30");
1034 1035 1036 1037 1038 1039 1040

#ifdef ENABLE_NONSTANDARD_GSM
	{
		PayloadType *pt;
		pt=payload_type_clone(&payload_type_gsm);
		pt->clock_rate=11025;
		rtp_profile_set_payload(&av_profile,114,pt);
1041 1042 1043 1044 1045
		linphone_payload_types=ms_list_append(linphone_payload_types,pt);
		pt=payload_type_clone(&payload_type_gsm);
		pt->clock_rate=22050;
		rtp_profile_set_payload(&av_profile,115,pt);
		linphone_payload_types=ms_list_append(linphone_payload_types,pt);
1046
	}
aymeric's avatar
aymeric committed
1047 1048
#endif

1049 1050 1051 1052 1053 1054 1055 1056
#ifdef VIDEO_ENABLED
	linphone_core_assign_payload_type(&payload_type_h263,34,NULL);
	linphone_core_assign_payload_type(&payload_type_theora,97,NULL);
	linphone_core_assign_payload_type(&payload_type_h263_1998,98,"CIF=1;QCIF=1");
	linphone_core_assign_payload_type(&payload_type_mp4v,99,"profile-level-id=3");
	linphone_core_assign_payload_type(&payload_type_x_snow,100,NULL);
	linphone_core_assign_payload_type(&payload_type_h264,102,NULL);
	linphone_core_assign_payload_type(&payload_type_h264,103,"packetization-mode=1");
1057 1058
#endif

aymeric's avatar
aymeric committed
1059
	ms_init();
1060

aymeric's avatar
aymeric committed
1061
	lc->config=lp_config_new(config_path);
1062 1063
	if (factory_config_path)
		lp_config_read_file(lc->config,factory_config_path);
1064

1065
	lc->sal=sal_init();
Simon Morlat's avatar
Simon Morlat committed
1066
	sal_set_user_pointer(lc->sal,lc);
Simon Morlat's avatar
Simon Morlat committed
1067
	sal_set_callbacks(lc->sal,&linphone_sal_callbacks);
1068 1069 1070
	if (lp_config_get_int(lc->config,"sip","use_session_timers",0)==1){
		sal_use_session_timers(lc->sal,200);
	}
smorlat's avatar
smorlat committed
1071
	sip_setup_register_all();
aymeric's avatar
aymeric committed
1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084
	sound_config_read(lc);
	net_config_read(lc);
	rtp_config_read(lc);
	codecs_config_read(lc);
	sip_config_read(lc); /* this will start eXosip*/
	video_config_read(lc);
	//autoreplier_config_init(&lc->autoreplier_conf);
	lc->prev_mode=LINPHONE_STATUS_ONLINE;
	lc->presence_mode=LINPHONE_STATUS_ONLINE;
	lc->max_call_logs=15;
	ui_config_read(lc);
	lc->vtable.display_status(lc,_("Ready"));
        gstate_new_state(lc, GSTATE_POWER_ON, NULL);
jehan's avatar
jehan committed
1085
	lc->auto_net_state_mon=lc->sip_conf.auto_net_state_mon;
jehan's avatar
jehan committed
1086

jehan's avatar
jehan committed
1087
    lc->ready=TRUE;
aymeric's avatar
aymeric committed
1088 1089
}

smorlat's avatar